LCR is now uses socket based mISDN V2 API
[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
15 extern "C" {
16 }
17 #include <q931.h>
18
19 #undef offsetof
20 #ifdef __compiler_offsetof
21 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
22 #else
23 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
24 #endif
25
26 #define container_of(ptr, type, member) ({                      \
27         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
28         (type *)( (char *)__mptr - offsetof(type,member) );})
29
30 // timeouts if activating/deactivating response from mISDN got lost
31 #define B_TIMER_ACTIVATING 1 // seconds
32 #define B_TIMER_DEACTIVATING 1 // seconds
33
34 /* list of mISDN ports */
35 struct mISDNport *mISDNport_first;
36
37 /* noise randomizer */
38 unsigned char mISDN_rand[256];
39 int mISDN_rand_count = 0;
40
41 unsigned long mt_assign_pid = ~0;
42
43 int mISDNsocket = -1;
44
45 int mISDN_initialize(void)
46 {
47         char filename[256];
48
49         /* try to open raw socket to check kernel */
50         mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
51         if (mISDNsocket < 0)
52         {
53                 fprintf(stderr, "Cannot open mISDN due to '%s'. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
54                 return(-1);
55         }
56
57         /* init mlayer3 */
58         init_layer3(4); // buffer of 4
59
60         /* open debug, if enabled and not only stack debugging */
61         if (options.deb)
62         {
63                 SPRINT(filename, "%s/debug.log", INSTALL_DATA);
64                 debug_fp = fopen(filename, "a");
65         }
66
67         if (options.deb & DEBUG_STACK)
68         {
69                 SPRINT(filename, "%s/debug_mISDN.log", INSTALL_DATA);
70                 mISDN_debug_init(0xffffffff, filename, filename, filename);
71         } else
72                 mISDN_debug_init(0, NULL, NULL, NULL);
73
74         return(0);
75 }
76
77 void mISDN_deinitialize(void)
78 {
79         cleanup_layer3();
80
81         mISDN_debug_close();
82
83         if (debug_fp)
84                 fclose(debug_fp);
85         debug_fp = NULL;
86
87         if (mISDNsocket > -1)
88                 close(mISDNsocket);
89 }
90
91 /*
92  * constructor
93  */
94 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
95 {
96         p_m_mISDNport = mISDNport;
97         p_m_portnum = mISDNport->portnum;
98         p_m_b_index = -1;
99         p_m_b_channel = 0;
100         p_m_b_exclusive = 0;
101         p_m_b_reserve = 0;
102         p_m_delete = 0;
103         p_m_hold = 0;
104         p_m_tx_gain = mISDNport->ifport->interface->tx_gain;
105         p_m_rx_gain = mISDNport->ifport->interface->rx_gain;
106         p_m_conf = 0;
107         p_m_txdata = 0;
108         p_m_delay = 0;
109         p_m_echo = 0;
110         p_m_tone = 0;
111         p_m_rxoff = 0;
112         p_m_joindata = 0;
113         p_m_dtmf = !mISDNport->ifport->nodtmf;
114         p_m_timeout = 0;
115         p_m_timer = 0;
116         p_m_remote_ref = 0; /* channel shall be exported to given remote */
117         p_m_remote_id = 0; /* channel shall be exported to given remote */
118         SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
119         
120         /* audio */
121         p_m_load = 0;
122         p_m_last_tv_sec = 0;
123
124         /* crypt */
125         p_m_crypt = 0;
126         p_m_crypt_listen = 0;
127         p_m_crypt_msg_loops = 0;
128         p_m_crypt_msg_loops = 0;
129         p_m_crypt_msg_len = 0;
130         p_m_crypt_msg[0] = '\0';
131         p_m_crypt_msg_current = 0;
132         p_m_crypt_key_len = 0;
133         p_m_crypt_listen = 0;
134         p_m_crypt_listen_state = 0;
135         p_m_crypt_listen_len = 0;
136         p_m_crypt_listen_msg[0] = '\0';
137         p_m_crypt_listen_crc = 0;
138         if (mISDNport->ifport->interface->bf_len >= 4 && mISDNport->ifport->interface->bf_len <= 56)
139         {
140                 memcpy(p_m_crypt_key, mISDNport->ifport->interface->bf_key, p_m_crypt_key_len);
141                 p_m_crypt_key_len = mISDNport->ifport->interface->bf_len;
142                 p_m_crypt = 1;
143         }
144
145         /* if any channel requested by constructor */
146         if (channel == CHANNEL_ANY)
147         {
148                 /* reserve channel */
149                 p_m_b_reserve = 1;
150                 mISDNport->b_reserved++;
151         }
152
153         /* reserve channel */
154         if (channel > 0) // only if constructor was called with a channel resevation
155                 seize_bchannel(channel, exclusive);
156
157         /* we increase the number of objects: */
158         mISDNport->use++;
159         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
160 }
161
162
163 /*
164  * destructor
165  */
166 PmISDN::~PmISDN()
167 {
168         struct lcr_msg *message;
169
170         /* remove bchannel relation */
171         drop_bchannel();
172
173         /* release epoint */
174         while (p_epointlist)
175         {
176                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
177                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
178                 message->param.disconnectinfo.cause = 16;
179                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
180                 message_put(message);
181                 /* remove from list */
182                 free_epointlist(p_epointlist);
183         }
184
185         /* we decrease the number of objects: */
186         p_m_mISDNport->use--;
187         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
188 }
189
190
191 /*
192  * trace
193  */
194 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
195 {
196         /* init trace with given values */
197         start_trace(mISDNport?mISDNport->portnum:0,
198                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
199                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
200                     port?port->p_dialinginfo.id:NULL,
201                     direction,
202                     CATEGORY_CH,
203                     port?port->p_serial:0,
204                     msgtext);
205 }
206
207
208 /*
209  * layer trace header
210  */
211 static struct isdn_message {
212         char *name;
213         unsigned long value;
214 } isdn_message[] = {
215         {"PH_ACTIVATE", L1_ACTIVATE_REQ},
216         {"PH_DEACTIVATE", L1_DEACTIVATE_REQ},
217         {"DL_ESTABLISH", L2_ESTABLISH_REQ},
218         {"DL_RELEASE", L2_RELEASE_REQ},
219         {"UNKNOWN", L3_UNKNOWN},
220         {"MT_TIMEOUT", L3_TIMEOUT_REQ},
221         {"MT_SETUP", L3_SETUP_REQ},
222         {"MT_SETUP_ACK", L3_SETUP_ACKNOWLEDGE_REQ},
223         {"MT_PROCEEDING", L3_PROCEEDING_REQ},
224         {"MT_ALERTING", L3_ALERTING_REQ},
225         {"MT_CONNECT", L3_CONNECT_REQ},
226         {"MT_CONNECT_ACK", L3_CONNECT_ACKNOWLEDGE_REQ},
227         {"MT_DISCONNECT", L3_DISCONNECT_REQ},
228         {"MT_RELEASE", L3_RELEASE_REQ},
229         {"MT_RELEASE_COMP", L3_RELEASE_COMPLETE_REQ},
230         {"MT_INFORMATION", L3_INFORMATION_REQ},
231         {"MT_PROGRESS", L3_PROGRESS_REQ},
232         {"MT_NOTIFY", L3_NOTIFY_REQ},
233         {"MT_SUSPEND", L3_SUSPEND_REQ},
234         {"MT_SUSPEND_ACK", L3_SUSPEND_ACKNOWLEDGE_REQ},
235         {"MT_SUSPEND_REJ", L3_SUSPEND_REJECT_REQ},
236         {"MT_RESUME", L3_RESUME_REQ},
237         {"MT_RESUME_ACK", L3_RESUME_ACKNOWLEDGE_REQ},
238         {"MT_RESUME_REJ", L3_RESUME_REJECT_REQ},
239         {"MT_HOLD", L3_HOLD_REQ},
240         {"MT_HOLD_ACK", L3_HOLD_ACKNOWLEDGE_REQ},
241         {"MT_HOLD_REJ", L3_HOLD_REJECT_REQ},
242         {"MT_RETRIEVE", L3_RETRIEVE_REQ},
243         {"MT_RETRIEVE_ACK", L3_RETRIEVE_ACKNOWLEDGE_REQ},
244         {"MT_RETRIEVE_REJ", L3_RETRIEVE_REJECT_REQ},
245         {"MT_FACILITY", L3_FACILITY_REQ},
246         {"MT_STATUS", L3_STATUS_REQ},
247         {"MT_RESTART", L3_RESTART_REQ},
248         {"MT_NEW_L3ID", L3_NEW_L3ID_REQ},
249         {"MT_RELEASE_L3ID", L3_RELEASE_L3ID_REQ},
250         {NULL, 0},
251 };
252 static char *isdn_prim[4] = {
253         " REQUEST",
254         " CONFIRM",
255         " INDICATION",
256         " RESPONSE",
257 };
258 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long msg, int direction)
259 {
260         int i;
261         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
262
263         /* select message and primitive text */
264         i = 0;
265         while(isdn_message[i].name)
266         {
267                 if (isdn_message[i].value == (msg&0xffffff00))
268                 {
269                         SCPY(msgtext, isdn_message[i].name);
270                         break;
271                 }
272                 i++;
273         }
274         SCAT(msgtext, isdn_prim[msg&0x00000003]);
275
276         /* add direction */
277         if (direction && (msg&0xffffff00)!=L3_NEW_L3ID_REQ && (msg&0xffffff00)!=L3_RELEASE_L3ID_REQ)
278         {
279                 if (mISDNport)
280                 {
281                         if (mISDNport->ntmode)
282                         {
283                                 if (direction == DIRECTION_OUT)
284                                         SCAT(msgtext, " N->U");
285                                 else
286                                         SCAT(msgtext, " N<-U");
287                         } else
288                         {
289                                 if (direction == DIRECTION_OUT)
290                                         SCAT(msgtext, " U->N");
291                                 else
292                                         SCAT(msgtext, " U<-N");
293                         }
294                 }
295         }
296
297         /* init trace with given values */
298         start_trace(mISDNport?mISDNport->portnum:0,
299                     mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
300                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
301                     port?port->p_dialinginfo.id:NULL,
302                     direction,
303                     CATEGORY_CH,
304                     port?port->p_serial:0,
305                     msgtext);
306 }
307
308
309 /*
310  * send control information to the channel (dsp-module)
311  */
312 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long sock, unsigned long c1, unsigned long c2, char *trace_name, int trace_value)
313 {
314         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
315         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
316         unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
317         int ret;
318
319         if (sock < 0)
320                 return;
321
322         ctrl->prim = PH_CONTROL_REQ;
323         ctrl->id = 0;
324         *d++ = c1;
325         *d++ = c2;
326         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
327         if (ret <= 0)
328                 PERROR("Failed to send to socket %d\n", sock);
329         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
330         if (c1 == DSP_CONF_JOIN)
331                 add_trace(trace_name, NULL, "0x%08x", trace_value);
332         else
333                 add_trace(trace_name, NULL, "%d", trace_value);
334         end_trace();
335 }
336
337 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, int sock, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
338 {
339         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
340         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
341         unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
342         int ret;
343
344         if (sock < 0)
345                 return;
346
347         ctrl->prim = PH_CONTROL_REQ;
348         ctrl->id = 0;
349         *d++ = c1;
350         memcpy(d, c2, c2_len);
351         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
352         if (ret <= 0)
353                 PERROR("Failed to send to socket %d\n", sock);
354         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
355         add_trace(trace_name, NULL, "%d", trace_value);
356         end_trace();
357 }
358
359
360 /*
361  * subfunction for bchannel_event
362  * create stack
363  */
364 static int _bchannel_create(struct mISDNport *mISDNport, int i)
365 {
366         int ret;
367         unsigned long on = 1;
368         struct sockaddr_mISDN addr;
369
370         if (mISDNport->b_socket[i] > -1)
371         {
372                 PERROR("Error: Socket already created for index %d\n", i);
373                 return(0);
374         }
375
376         /* open socket */
377 //#warning testing without DSP
378 //      mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
379         mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
380         if (mISDNport->b_socket[i] < 0)
381         {
382                 PERROR("Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
383                 return(0);
384         }
385         
386         /* set nonblocking io */
387         ret = ioctl(mISDNport->b_socket[i], FIONBIO, &on);
388         if (ret < 0)
389         {
390                 PERROR("Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
391                 close(mISDNport->b_socket[i]);
392                 mISDNport->b_socket[i] = -1;
393                 return(0);
394         }
395
396         /* bind socket to bchannel */
397         addr.family = AF_ISDN;
398         addr.dev = mISDNport->portnum-1;
399         addr.channel = i+1+(i>=15);
400         ret = bind(mISDNport->b_socket[i], (struct sockaddr *)&addr, sizeof(addr));
401         if (ret < 0)
402         {
403                 PERROR("Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
404                 close(mISDNport->b_socket[i]);
405                 mISDNport->b_socket[i] = -1;
406                 return(0);
407         }
408
409         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
410         add_trace("channel", NULL, "%d", i+1+(i>=15));
411         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
412         end_trace();
413
414         return(1);
415 }
416
417
418 /*
419  * subfunction for bchannel_event
420  * activate / deactivate request
421  */
422 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
423 {
424         struct mISDNhead act;
425         int ret;
426
427         if (mISDNport->b_socket[i] < 0)
428                 return;
429         act.prim = (activate)?PH_ACTIVATE_REQ:PH_DEACTIVATE_REQ; 
430         act.id = 0;
431         ret = sendto(mISDNport->b_socket[i], &act, MISDN_HEADER_LEN, 0, NULL, 0);
432         if (ret <= 0)
433                 PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
434
435         /* trace */
436         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
437         add_trace("channel", NULL, "%d", i+1+(i>=15));
438         if (mISDNport->b_timer[i])
439                 add_trace("event", NULL, "timeout recovery");
440         end_trace();
441 }
442
443
444 /*
445  * subfunction for bchannel_event
446  * set features
447  */
448 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
449 {
450         struct PmISDN *port;
451         int handle;
452
453         if (mISDNport->b_socket[i] < 0)
454                 return;
455         handle = mISDNport->b_socket[i];
456         port = mISDNport->b_port[i];
457         if (!port)
458         {
459                 PERROR("bchannel index i=%d not associated with a port object\n", i);
460                 return;
461         }
462
463         /* set dsp features */
464         if (port->p_m_txdata)
465                 ph_control(mISDNport, port, handle, (port->p_m_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
466         if (port->p_m_delay)
467                 ph_control(mISDNport, port, handle, DSP_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
468         if (port->p_m_tx_gain)
469                 ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
470         if (port->p_m_rx_gain)
471                 ph_control(mISDNport, port, handle, DSP_VOL_CHANGE_RX, port->p_m_rx_gain, "DSP-RX_GAIN", port->p_m_rx_gain);
472         if (port->p_m_pipeline[0])
473                 ph_control_block(mISDNport, port, handle, DSP_PIPELINE_CFG, port->p_m_pipeline, strlen(port->p_m_pipeline)+1, "DSP-PIPELINE", 0);
474         if (port->p_m_conf)
475                 ph_control(mISDNport, port, handle, DSP_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
476         if (port->p_m_echo)
477                 ph_control(mISDNport, port, handle, DSP_ECHO_ON, 0, "DSP-ECHO", 1);
478         if (port->p_m_tone)
479                 ph_control(mISDNport, port, handle, DSP_TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
480         if (port->p_m_rxoff)
481                 ph_control(mISDNport, port, handle, DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
482 //      if (port->p_m_txmix)
483 //              ph_control(mISDNport, port, handle, DSP_MIX_ON, 0, "DSP-MIX", 1);
484         if (port->p_m_dtmf)
485                 ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
486         if (port->p_m_crypt)
487                 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);
488 }
489
490 /*
491  * subfunction for bchannel_event
492  * destroy stack
493  */
494 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
495 {
496         if (mISDNport->b_socket[i] < 0)
497                 return;
498         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
499         add_trace("channel", NULL, "%d", i+1+(i>=15));
500         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
501         end_trace();
502         close(mISDNport->b_socket[i]);
503         mISDNport->b_socket[i] = -1;
504 }
505
506
507 /*
508 bchannel procedure
509 ------------------
510
511 A bchannel goes through the following states in this order:
512
513 - B_STATE_IDLE
514 No one is using the bchannel.
515 It is available and not linked to Port class, nor reserved.
516
517 - B_STATE_ACTIVATING
518 The bchannel stack is created and an activation request is sent.
519 It MAY be linked to Port class, but already unlinked due to Port class removal.
520
521 - B_STATE_ACTIVE
522 The bchannel is active and cofigured to the Port class needs.
523 Also it is linked to a Port class, otherwhise it would be deactivated.
524
525 - B_STATE_DEACTIVATING
526 The bchannel is in deactivating state, due to deactivation request.
527 It may be linked to a Port class, that likes to reactivate it.
528
529 - B_STATE_IDLE
530 See above.
531 After deactivating bchannel, and if not used, the bchannel becomes idle again.
532
533 Also the bchannel may be exported, but only if the state is or becomes idle:
534
535 - B_STATE_EXPORTING
536 The bchannel assignment has been sent to the remove application.
537
538 - B_STATE_REMOTE
539 The bchannel assignment is acknowledged by the remote application.
540
541 - B_STATE_IMPORTING
542 The bchannel is re-imported by mISDN port object.
543
544 - B_STATE_IDLE
545 See above.
546 After re-importing bchannel, and if not used, the bchannel becomes idle again.
547
548
549 A bchannel can have the following events:
550
551 - B_EVENT_USE
552 A bchannel is required by a Port class.
553
554 - B_EVENT_ACTIVATED
555 The bchannel beomes active.
556
557 - B_EVENT_DROP
558 The bchannel is not required by Port class anymore
559
560 - B_EVENT_DEACTIVATED
561 The bchannel becomes inactive.
562
563 - B_EVENT_EXPORTED
564 The bchannel is now used by remote application.
565
566 - B_EVENT_IMPORTED
567 The bchannel is not used by remote application.
568
569 - B_EVENT_EXPORTREQUEST
570 The bchannel shall be exported to the remote application.
571
572 - B_EVENT_IMPORTREQUEST
573 The bchannel is released from the remote application.
574
575 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
576
577 if an export request is receive by remote application, p_m_remote_* is set.
578 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.)
579 - set on export request from remote application (if port is assigned)
580 - set on channel use, if requested by remote application (p_m_remote_*)
581 - cleared on drop request
582
583 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
584 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
585 the bchannel import/export is acknowledged with stack given.
586
587 if exporting, b_remote_*[index] is set to the remote socket id.
588 if importing has been acknowledged. b_remote_*[index] is cleared.
589
590 */
591
592 /*
593  * process bchannel events
594  * - mISDNport is a pointer to the port's structure
595  * - i is the index of the bchannel
596  * - event is the B_EVENT_* value
597  * - port is the PmISDN class pointer
598  */
599 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
600 {
601         class PmISDN *b_port = mISDNport->b_port[i];
602         int state = mISDNport->b_state[i];
603         double timer = mISDNport->b_timer[i];
604         unsigned long p_m_remote_ref = 0;
605         unsigned long p_m_remote_id = 0;
606         int p_m_tx_gain = 0;
607         int p_m_rx_gain = 0;
608         char *p_m_pipeline = NULL;
609         unsigned char *p_m_crypt_key = NULL;
610         int p_m_crypt_key_len = 0;
611         int p_m_crypt_key_type = 0;
612         unsigned long portid = (mISDNport->portnum<<8) + i+1+(i>=15);
613
614         if (b_port)
615         {
616                 p_m_remote_id = b_port->p_m_remote_id;
617                 p_m_remote_ref = b_port->p_m_remote_ref;
618                 p_m_tx_gain = b_port->p_m_tx_gain;
619                 p_m_rx_gain = b_port->p_m_rx_gain;
620                 p_m_pipeline = b_port->p_m_pipeline;
621                 p_m_crypt_key = b_port->p_m_crypt_key;
622                 p_m_crypt_key_len = b_port->p_m_crypt_key_len;
623                 p_m_crypt_key_type = /*b_port->p_m_crypt_key_type*/1;
624         }
625
626         switch(event)
627         {
628                 case B_EVENT_USE:
629                 /* port must be linked in order to allow activation */
630                 if (!b_port)
631                         FATAL("bchannel must be linked to a Port class\n");
632                 switch(state)
633                 {
634                         case B_STATE_IDLE:
635                         if (p_m_remote_ref)
636                         {
637                                 /* export bchannel */
638                                 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);
639                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
640                                 add_trace("type", NULL, "assign");
641                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
642                                 end_trace();
643                                 state = B_STATE_EXPORTING;
644                                 mISDNport->b_remote_id[i] = p_m_remote_id;
645                                 mISDNport->b_remote_ref[i] = p_m_remote_ref;
646                         } else
647                         {
648                                 /* create stack and send activation request */
649                                 if (_bchannel_create(mISDNport, i))
650                                 {
651                                         _bchannel_activate(mISDNport, i, 1);
652                                         state = B_STATE_ACTIVATING;
653                                         timer = now_d + B_TIMER_ACTIVATING;
654                                 }
655                         }
656                         break;
657
658                         case B_STATE_ACTIVATING:
659                         case B_STATE_EXPORTING:
660                         /* do nothing, because it is already activating */
661                         break;
662
663                         case B_STATE_DEACTIVATING:
664                         case B_STATE_IMPORTING:
665                         /* do nothing, because we must wait until we can reactivate */
666                         break;
667
668                         default:
669                         /* problems that might ocurr:
670                          * B_EVENT_USE is received when channel already in use.
671                          * bchannel exported, but not freed by other port
672                          */
673                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
674                 }
675                 break;
676
677                 case B_EVENT_EXPORTREQUEST:
678                 /* special case where the bchannel is requested by remote */
679                 if (!p_m_remote_ref)
680                 {
681                         PERROR("export request without remote channel set, please correct.\n");
682                         break;
683                 }
684                 switch(state)
685                 {
686                         case B_STATE_IDLE:
687                         /* in case, the bchannel is exported right after seize_bchannel */
688                         /* export bchannel */
689                         /* p_m_remote_id is set, when this event happens. */
690                         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);
691                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
692                         add_trace("type", NULL, "assign");
693                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
694                         end_trace();
695                         state = B_STATE_EXPORTING;
696                         mISDNport->b_remote_id[i] = p_m_remote_id;
697                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
698                         break;
699
700                         case B_STATE_ACTIVATING:
701                         case B_STATE_EXPORTING:
702                         /* do nothing, because it is already activating */
703                         break;
704
705                         case B_STATE_DEACTIVATING:
706                         case B_STATE_IMPORTING:
707                         /* do nothing, because we must wait until we can reactivate */
708                         break;
709
710                         case B_STATE_ACTIVE:
711                         /* bchannel is active, so we deactivate */
712                         _bchannel_activate(mISDNport, i, 0);
713                         state = B_STATE_DEACTIVATING;
714                         timer = now_d + B_TIMER_DEACTIVATING;
715                         break;
716
717                         default:
718                         /* problems that might ocurr:
719                          * ... when channel already in use.
720                          * bchannel exported, but not freed by other port
721                          */
722                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
723                 }
724                 break;
725
726                 case B_EVENT_IMPORTREQUEST:
727                 /* special case where the bchannel is released by remote */
728                 if (p_m_remote_ref)
729                 {
730                         PERROR("import request with remote channel set, please correct.\n");
731                         break;
732                 }
733                 switch(state)
734                 {
735                         case B_STATE_IDLE:
736                         case B_STATE_ACTIVE:
737                         /* bchannel is not exported */
738                         break;
739
740                         case B_STATE_ACTIVATING:
741                         case B_STATE_EXPORTING:
742                         /* do nothing because we must wait until bchanenl is active before deactivating */
743                         break;
744
745                         case B_STATE_REMOTE:
746                         /* bchannel is exported, so we re-import */
747                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
748                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
749                         add_trace("type", NULL, "remove");
750                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
751                         end_trace();
752                         state = B_STATE_IMPORTING;
753                         break;
754
755                         case B_STATE_DEACTIVATING:
756                         case B_STATE_IMPORTING:
757                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
758                         break;
759
760                         default:
761                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
762                 }
763                 break;
764
765                 case B_EVENT_ACTIVATED:
766                 timer = 0;
767                 switch(state)
768                 {
769                         case B_STATE_ACTIVATING:
770                         if (b_port && !p_m_remote_id)
771                         {
772                                 /* bchannel is active and used by Port class, so we configure bchannel */
773                                 _bchannel_configure(mISDNport, i);
774                                 state = B_STATE_ACTIVE;
775                         } else
776                         {
777                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
778                                 _bchannel_activate(mISDNport, i, 0);
779                                 state = B_STATE_DEACTIVATING;
780                                 timer = now_d + B_TIMER_DEACTIVATING;
781                         }
782                         break;
783
784                         default:
785                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
786                 }
787                 break;
788
789                 case B_EVENT_EXPORTED:
790                 switch(state)
791                 {
792                         case B_STATE_EXPORTING:
793                         if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i])
794                         {
795                                 /* remote export done */
796                                 state = B_STATE_REMOTE;
797                         } else
798                         {
799                                 /* bchannel is now exported, but we need bchannel back
800                                  * OR bchannel is not used anymore
801                                  * OR bchannel has been exported to an obsolete ref,
802                                  * so reimport, to later export to new remote */
803                                 message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
804                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
805                                 add_trace("type", NULL, "remove");
806                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
807                                 end_trace();
808                                 state = B_STATE_IMPORTING;
809                         }
810                         break;
811
812                         default:
813                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
814                 }
815                 break;
816
817                 case B_EVENT_DROP:
818                 if (!b_port)
819                         FATAL("bchannel must be linked to a Port class\n");
820                 switch(state)
821                 {
822                         case B_STATE_IDLE:
823                         /* bchannel is idle due to an error, so we do nothing */
824                         break;
825
826                         case B_STATE_ACTIVATING:
827                         case B_STATE_EXPORTING:
828                         /* do nothing because we must wait until bchanenl is active before deactivating */
829                         break;
830
831                         case B_STATE_ACTIVE:
832                         /* bchannel is active, so we deactivate */
833                         _bchannel_activate(mISDNport, i, 0);
834                         state = B_STATE_DEACTIVATING;
835                         timer = now_d + B_TIMER_DEACTIVATING;
836                         break;
837
838                         case B_STATE_REMOTE:
839                         /* bchannel is exported, so we re-import */
840                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
841                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
842                         add_trace("type", NULL, "remove");
843                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
844                         end_trace();
845                         state = B_STATE_IMPORTING;
846                         break;
847
848                         case B_STATE_DEACTIVATING:
849                         case B_STATE_IMPORTING:
850                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
851                         break;
852
853                         default:
854                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
855                 }
856                 break;
857
858                 case B_EVENT_DEACTIVATED:
859                 timer = 0;
860                 switch(state)
861                 {
862                         case B_STATE_IDLE:
863                         /* ignore due to deactivation confirm after unloading */
864                         break;
865
866                         case B_STATE_DEACTIVATING:
867                         _bchannel_destroy(mISDNport, i);
868                         state = B_STATE_IDLE;
869                         if (b_port)
870                         {
871                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
872                                 if (p_m_remote_ref)
873                                 {
874                                         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);
875                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
876                                         add_trace("type", NULL, "assign");
877                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
878                                         end_trace();
879                                         state = B_STATE_EXPORTING;
880                                         mISDNport->b_remote_id[i] = p_m_remote_id;
881                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
882                                 } else
883                                 {
884                                         if (_bchannel_create(mISDNport, i))
885                                         {
886                                                 _bchannel_activate(mISDNport, i, 1);
887                                                 state = B_STATE_ACTIVATING;
888                                                 timer = now_d + B_TIMER_ACTIVATING;
889                                         }
890                                 }
891                         }
892                         break;
893
894                         default:
895                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
896                 }
897                 break;
898
899                 case B_EVENT_IMPORTED:
900                 switch(state)
901                 {
902                         case B_STATE_IMPORTING:
903                         state = B_STATE_IDLE;
904                         mISDNport->b_remote_id[i] = 0;
905                         mISDNport->b_remote_ref[i] = 0;
906                         if (b_port)
907                         {
908                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
909                                 if (p_m_remote_ref)
910                                 {
911                                         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);
912                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
913                                         add_trace("type", NULL, "assign");
914                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
915                                         end_trace();
916                                         state = B_STATE_EXPORTING;
917                                         mISDNport->b_remote_id[i] = p_m_remote_id;
918                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
919                                 } else
920                                 {
921                                         if (_bchannel_create(mISDNport, i))
922                                         {
923                                                 _bchannel_activate(mISDNport, i, 1);
924                                                 state = B_STATE_ACTIVATING;
925                                                 timer = now_d + B_TIMER_ACTIVATING;
926                                         }
927                                 }
928                         }
929                         break;
930
931                         default:
932                         /* ignore, because not assigned */
933                         ;
934                 }
935                 break;
936
937                 case B_EVENT_TIMEOUT:
938                 timer = 0;
939                 switch(state)
940                 {
941                         case B_STATE_IDLE:
942                         /* ignore due to deactivation confirm after unloading */
943                         break;
944
945                         case B_STATE_ACTIVATING:
946                         _bchannel_activate(mISDNport, i, 1);
947                         timer = now_d + B_TIMER_ACTIVATING;
948                         break;
949
950                         case B_STATE_DEACTIVATING:
951                         _bchannel_activate(mISDNport, i, 0);
952                         timer = now_d + B_TIMER_DEACTIVATING;
953                         break;
954
955                         default:
956                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
957                 }
958                 break;
959
960                 default:
961                 PERROR("Illegal event %d, please correct.\n", event);
962         }
963
964         mISDNport->b_state[i] = state;
965         mISDNport->b_timer[i] = timer;
966 }
967
968
969
970
971 /*
972  * check for available channel and reserve+set it.
973  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
974  * give exclusiv flag
975  * returns -(cause value) or x = channel x or 0 = no channel
976  * NOTE: no activation is done here
977  */
978 int PmISDN::seize_bchannel(int channel, int exclusive)
979 {
980         int i;
981
982         /* the channel is what we have */
983         if (p_m_b_channel == channel)
984                 return(channel);
985
986         /* if channel already in use, release it */
987         if (p_m_b_channel)
988                 drop_bchannel();
989
990         /* if CHANNEL_NO */
991         if (channel==CHANNEL_NO || channel==0)
992                 return(0);
993         
994         /* is channel in range ? */
995         if (channel==16
996          || (channel>p_m_mISDNport->b_num && channel<16)
997          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
998                 return(-6); /* channel unacceptable */
999
1000         /* request exclusive channel */
1001         if (exclusive && channel>0)
1002         {
1003                 i = channel-1-(channel>16);
1004                 if (p_m_mISDNport->b_port[i])
1005                         return(-44); /* requested channel not available */
1006                 goto seize;
1007         }
1008
1009         /* ask for channel */
1010         if (channel>0)
1011         {
1012                 i = channel-1-(channel>16);
1013                 if (p_m_mISDNport->b_port[i] == NULL)
1014                         goto seize;
1015         }
1016
1017         /* search for channel */
1018         i = 0;
1019         while(i < p_m_mISDNport->b_num)
1020         {
1021                 if (!p_m_mISDNport->b_port[i])
1022                 {
1023                         channel = i+1+(i>=15);
1024                         goto seize;
1025                 }
1026                 i++;
1027         }
1028         return(-34); /* no free channel */
1029
1030 seize:
1031         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
1032
1033         /* link Port */
1034         p_m_mISDNport->b_port[i] = this;
1035         p_m_b_index = i;
1036         p_m_b_channel = channel;
1037         p_m_b_exclusive = exclusive;
1038
1039         /* reserve channel */
1040         if (!p_m_b_reserve)
1041         {
1042                 p_m_b_reserve = 1;
1043                 p_m_mISDNport->b_reserved++;
1044         }
1045
1046         return(channel);
1047 }
1048
1049 /*
1050  * drop reserved channel and unset it.
1051  * deactivation is also done
1052  */
1053 void PmISDN::drop_bchannel(void)
1054 {
1055         /* unreserve channel */
1056         if (p_m_b_reserve)
1057                 p_m_mISDNport->b_reserved--;
1058         p_m_b_reserve = 0;
1059
1060         /* if not in use */
1061         if (p_m_b_index < 0)
1062                 return;
1063         if (!p_m_b_channel)
1064                 return;
1065
1066         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1067
1068         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1069                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1070         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1071         p_m_b_index = -1;
1072         p_m_b_channel = 0;
1073         p_m_b_exclusive = 0;
1074 }
1075
1076 /* process bchannel export/import message from join */
1077 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
1078 {
1079         class Endpoint *epoint;
1080         class Port *port;
1081         class PmISDN *isdnport;
1082         struct mISDNport *mISDNport;
1083         int i, ii;
1084
1085         switch(type)
1086         {
1087                 case BCHANNEL_REQUEST:
1088                 /* find the port object for the join object ref */
1089                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1090                 {
1091                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1092                         return;
1093                 }
1094                 if (!epoint->ep_portlist)
1095                 {
1096                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1097                         return;
1098                 }
1099                 if (epoint->ep_portlist->next)
1100                 {
1101                         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);
1102                 }
1103                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1104                 {
1105                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1106                         return;
1107                 }
1108                 if ((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN)
1109                 {
1110                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1111                 }
1112                 isdnport = (class PmISDN *)port;
1113
1114                 /* assign */
1115                 if (isdnport->p_m_remote_id)
1116                 {
1117                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1118                         break;
1119                 }
1120                 mISDNport = isdnport->p_m_mISDNport;
1121                 i = isdnport->p_m_b_index;
1122                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1123                 add_trace("type", NULL, "export request");
1124                 end_trace();
1125                 isdnport->p_m_remote_ref = joinremote->j_serial;
1126                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1127                 if (mISDNport && i>=0)
1128                 {
1129                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1130                 }
1131                 break;
1132
1133                 case BCHANNEL_RELEASE:
1134                 /* find the port object for the join object ref */
1135                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1136                 {
1137                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1138                         return;
1139                 }
1140                 if (!epoint->ep_portlist)
1141                 {
1142                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1143                         return;
1144                 }
1145                 if (epoint->ep_portlist->next)
1146                 {
1147                         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);
1148                 }
1149                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1150                 {
1151                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1152                         return;
1153                 }
1154                 if ((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN)
1155                 {
1156                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1157                 }
1158                 isdnport = (class PmISDN *)port;
1159
1160                 /* release */
1161                 if (!isdnport->p_m_remote_id)
1162                 {
1163                         PERROR("join %d recevied bchannel release from remote, but channel is already released.\n", joinremote->j_serial);
1164                         break;
1165                 }
1166                 mISDNport = isdnport->p_m_mISDNport;
1167                 i = isdnport->p_m_b_index;
1168                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1169                 add_trace("type", NULL, "export request");
1170                 end_trace();
1171                 isdnport->p_m_remote_ref = 0;
1172                 isdnport->p_m_remote_id = 0;
1173                 if (mISDNport && i>=0)
1174                 {
1175                         bchannel_event(mISDNport, i, B_EVENT_IMPORTREQUEST);
1176                 }
1177                 break;
1178
1179                 case BCHANNEL_ASSIGN_ACK:
1180                 case BCHANNEL_REMOVE_ACK:
1181                 /* find mISDNport for stack ID */
1182                 mISDNport = mISDNport_first;
1183                 while(mISDNport)
1184                 {
1185                         i = 0;
1186                         ii = mISDNport->b_num;
1187                         while(i < ii)
1188                         {
1189                                 if ((unsigned long)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1190                                         break;
1191                                 i++;
1192                         }
1193                         if (i != ii)
1194                                 break;
1195                         mISDNport = mISDNport->next;
1196                 }
1197                 if (!mISDNport)
1198                 {
1199                         PERROR("received assign/remove ack for bchannel's handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1200                         break;
1201                 }
1202                 /* mISDNport may now be set or NULL */
1203                 
1204                 /* set */
1205                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1206                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1207                 end_trace();
1208                 if (mISDNport && i>=0)
1209                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1210                 break;
1211                 default:
1212                 PERROR("received wrong bchannel message type %d from remote\n", type);
1213         }
1214 }
1215
1216
1217 /*
1218  * handler
1219
1220 audio transmission procedure:
1221 -----------------------------
1222
1223 * priority
1224 three sources of audio transmission:
1225 - crypto-data high priority
1226 - tones high priority (also high)
1227 - remote-data low priority
1228
1229 * elapsed
1230 a variable that temporarily shows the number of samples elapsed since last transmission process.
1231 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1232
1233 * load
1234 a variable that is increased whenever data is transmitted.
1235 it is decreased while time elapses. it stores the number of samples that
1236 are currently loaded to dsp module.
1237 since clock in dsp module is the same clock for user space process, these 
1238 times have no skew.
1239
1240 * levels
1241 there are two levels:
1242 ISDN_LOAD will give the load that have to be kept in dsp.
1243 ISDN_MAXLOAD will give the maximum load before dropping.
1244
1245 * procedure for low priority data
1246 see txfromup() for procedure
1247 in short: remote data is ignored during high priority tones
1248
1249 * procedure for high priority data
1250 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1251 if no more data is available, load becomes empty again.
1252
1253 'load' variable:
1254 0                    ISDN_LOAD           ISDN_MAXLOAD
1255 +--------------------+----------------------+
1256 |                    |                      |
1257 +--------------------+----------------------+
1258
1259 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1260 0                    ISDN_LOAD           ISDN_MAXLOAD
1261 +--------------------+----------------------+
1262 |TTTTTTTTTTTTTTTTTTTT|                      |
1263 +--------------------+----------------------+
1264
1265 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1266 0                    ISDN_LOAD           ISDN_MAXLOAD
1267 +--------------------+----------------------+
1268 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1269 +--------------------+----------------------+
1270
1271  */
1272 int PmISDN::handler(void)
1273 {
1274         struct lcr_msg *message;
1275         int elapsed = 0;
1276         int ret;
1277
1278         if ((ret = Port::handler()))
1279                 return(ret);
1280
1281         /* get elapsed */
1282         if (p_m_last_tv_sec)
1283         {
1284                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1285                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1286         } else
1287         {
1288                 /* set clock of first process ever in this instance */
1289                 p_m_last_tv_sec = now_tv.tv_sec;
1290                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1291         }
1292         /* process only if we have a minimum of samples, to make packets not too small */
1293         if (elapsed >= ISDN_TRANSMIT)
1294         {
1295                 /* set clock of last process! */
1296                 p_m_last_tv_sec = now_tv.tv_sec;
1297                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1298
1299                 /* update load */
1300                 if (elapsed < p_m_load)
1301                         p_m_load -= elapsed;
1302                 else
1303                         p_m_load = 0;
1304
1305                 /* to send data, tone must be active OR crypt messages must be on */
1306                 if ((p_tone_name[0] || p_m_crypt_msg_loops)
1307                  && (p_m_load < ISDN_LOAD)
1308                  && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones))
1309                 {
1310                         int tosend = ISDN_LOAD - p_m_load, length; 
1311                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1312                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1313                         unsigned char *p = buf+MISDN_HEADER_LEN;
1314
1315                         /* copy crypto loops */
1316                         while (p_m_crypt_msg_loops && tosend)
1317                         {
1318                                 /* how much do we have to send */
1319                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1320
1321                                 /* clip tosend */
1322                                 if (length > tosend)
1323                                         length = tosend;
1324
1325                                 /* copy message (part) to buffer */
1326                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1327
1328                                 /* new position */
1329                                 p_m_crypt_msg_current += length;
1330                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1331                                 {
1332                                         /* next loop */
1333                                         p_m_crypt_msg_current = 0;
1334                                         p_m_crypt_msg_loops--;
1335 //                                      puts("eine loop weniger");
1336                                 }
1337
1338                                 /* new length */
1339                                 tosend -= length;
1340                         }
1341
1342                         /* copy tones */
1343                         if (p_tone_name[0] && tosend)
1344                         {
1345                                 tosend -= read_audio(p, tosend);
1346                         }
1347
1348                         /* send data */
1349                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE && ISDN_LOAD-p_m_load-tosend > 0)
1350                         {
1351                                 frm->prim = PH_DATA_REQ;
1352                                 frm->id = 0;
1353                                 ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1354                                 if (ret <= 0)
1355                                         PERROR("Failed to send to socket %d (samples = %d)\n", p_m_mISDNport->b_socket[p_m_b_index], ISDN_LOAD-p_m_load-tosend);
1356                         }
1357                         p_m_load += ISDN_LOAD - p_m_load - tosend;
1358                 }
1359         }
1360
1361         // NOTE: deletion is done by the child class
1362
1363         /* handle timeouts */
1364         if (p_m_timeout)
1365         {
1366                 if (p_m_timer+p_m_timeout < now_d)
1367                 {
1368                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1369                         p_m_timeout = 0;
1370                         /* send timeout to endpoint */
1371                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1372                         message->param.state = p_state;
1373                         message_put(message);
1374                         return(1);
1375                 }
1376         }
1377         
1378         return(0); /* nothing done */
1379 }
1380
1381
1382 /*
1383  * whenever we get audio data from bchannel, we process it here
1384  */
1385 void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
1386 {
1387         unsigned long cont = *((unsigned long *)data);
1388         unsigned char *data_temp;
1389         unsigned long length_temp;
1390         struct lcr_msg *message;
1391         unsigned char *p;
1392         int l;
1393
1394         if (hh->prim == PH_CONTROL_IND)
1395         {
1396                 if (len < 4)
1397                 {
1398                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1399                         return;
1400                 }
1401                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1402                 {
1403                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1404                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1405                         end_trace();
1406                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1407                         message->param.dtmf = cont & DTMF_TONE_MASK;
1408                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1409                         message_put(message);
1410                         return;
1411                 }
1412                 switch(cont)
1413                 {
1414                         case DSP_BF_REJECT:
1415                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1416                         add_trace("DSP-CRYPT", NULL, "error");
1417                         end_trace();
1418                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1419                         message->param.crypt.type = CC_ERROR_IND;
1420                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1421                         message_put(message);
1422                         break;
1423
1424                         case DSP_BF_ACCEPT:
1425                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1426                         add_trace("DSP-CRYPT", NULL, "ok");
1427                         end_trace();
1428                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1429                         message->param.crypt.type = CC_ACTBF_CONF;
1430                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1431                         message_put(message);
1432                         break;
1433
1434                         default:
1435                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1436                         add_trace("unknown", NULL, "0x%x", cont);
1437                         end_trace();
1438                 }
1439                 return;
1440         }
1441         if (hh->prim == PH_CONTROL_IND)
1442         {
1443                 switch(hh->id)
1444                 {
1445                         default:
1446                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1447                         add_trace("unknown", NULL, "0x%x", hh->id);
1448                         end_trace();
1449                 }
1450                 return;
1451         }
1452         if (hh->prim == PH_DATA_REQ || hh->prim == DL_DATA_REQ)
1453         {
1454                 if (!p_m_txdata)
1455                 {
1456                         /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1457                         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1458                         return;
1459                 }
1460                 /* see below (same condition) */
1461                 if (p_state!=PORT_STATE_CONNECT
1462                          && !p_m_mISDNport->tones)
1463                         return;
1464 //              printf(".");fflush(stdout);return;
1465                 if (p_record)
1466                         record(data, len, 1); // from up
1467                 return;
1468         }
1469         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1470         {
1471                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1472                 return;
1473         }
1474
1475         /* calls will not process any audio data unless
1476          * the call is connected OR tones feature is enabled.
1477          */
1478 #ifndef DEBUG_COREBRIDGE
1479         if (p_state!=PORT_STATE_CONNECT
1480          && !p_m_mISDNport->tones)
1481                 return;
1482 #endif
1483
1484 #if 0
1485         /* the bearer capability must be audio in order to send and receive
1486          * audio prior or after connect.
1487          */
1488         if (!(p_bearerinfo.capability&CLASS_CAPABILITY_AUDIO) && p_state!=PORT_STATE_CONNECT)
1489                 return;
1490 #endif
1491
1492         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1493         if (p_m_rxoff)
1494         {
1495                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1496                 return;
1497         }
1498
1499         /* record data */
1500         if (p_record)
1501                 record(data, len, 0); // from down
1502
1503         /* randomize and listen to crypt message if enabled */
1504         if (p_m_crypt_listen)
1505         {
1506                 /* the noisy randomizer */
1507                 p = data;
1508                 l = len;
1509                 while(l--)
1510                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1511
1512                 cryptman_listen_bch(data, len);
1513         }
1514
1515         p = data;
1516
1517         /* send data to epoint */
1518         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1519         {
1520                 length_temp = len;
1521                 data_temp = p;
1522                 while(length_temp)
1523                 {
1524                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1525                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1526                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1527                         message_put(message);
1528                         if (length_temp <= sizeof(message->param.data.data))
1529                                 break;
1530                         data_temp += sizeof(message->param.data.data);
1531                         length_temp -= sizeof(message->param.data.data);
1532                 }
1533         }
1534 }
1535
1536
1537 /*
1538  * set echotest
1539  */
1540 void PmISDN::set_echotest(int echo)
1541 {
1542         if (p_m_echo != echo)
1543         {
1544                 p_m_echo = echo;
1545                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1546                 if (p_m_b_channel)
1547                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1548                                 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);
1549         }
1550 }
1551
1552 /*
1553  * set tone
1554  */
1555 void PmISDN::set_tone(char *dir, char *tone)
1556 {
1557         int id;
1558
1559         if (!tone)
1560                 tone = "";
1561         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1562         if (!tone[0])
1563         {
1564                 id = TONE_OFF;
1565                 goto setdsp;
1566         }
1567
1568         /* check if we NOT really have to use a dsp-tone */
1569         if (!options.dsptones)
1570         {
1571                 nodsp:
1572                 if (p_m_tone)
1573                 if (p_m_b_index > -1)
1574                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1575                 {
1576                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1577                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], DSP_TONE_PATT_OFF, 0, "DSP-TONE", 0);
1578                 }
1579                 p_m_tone = 0;
1580                 Port::set_tone(dir, tone);
1581                 return;
1582         }
1583         if (p_tone_dir[0])
1584                 goto nodsp;
1585
1586         /* now we USE dsp-tone, convert name */
1587         else if (!strcmp(tone, "dialtone"))
1588         {
1589                 switch(options.dsptones) {
1590                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1591                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1592                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1593                 }
1594         } else if (!strcmp(tone, "dialpbx"))
1595         {
1596                 switch(options.dsptones) {
1597                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1598                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1599                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1600                 }
1601         } else if (!strcmp(tone, "ringing"))
1602         {
1603                 switch(options.dsptones) {
1604                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1605                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1606                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1607                 }
1608         } else if (!strcmp(tone, "ringpbx"))
1609         {
1610                 switch(options.dsptones) {
1611                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1612                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1613                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1614                 }
1615         } else if (!strcmp(tone, "busy"))
1616         {
1617                 busy:
1618                 switch(options.dsptones) {
1619                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1620                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1621                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1622                 }
1623         } else if (!strcmp(tone, "release"))
1624         {
1625                 hangup:
1626                 switch(options.dsptones) {
1627                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1628                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1629                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1630                 }
1631         } else if (!strcmp(tone, "cause_10"))
1632                 goto hangup;
1633         else if (!strcmp(tone, "cause_11"))
1634                 goto busy;
1635         else if (!strcmp(tone, "cause_22"))
1636         {
1637                 switch(options.dsptones) {
1638                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1639                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1640                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1641                 }
1642         } else if (!strncmp(tone, "cause_", 6))
1643                 id = TONE_SPECIAL_INFO;
1644         else
1645                 id = TONE_OFF;
1646
1647         /* if we have a tone that is not supported by dsp */
1648         if (id==TONE_OFF && tone[0])
1649                 goto nodsp;
1650
1651         setdsp:
1652         if (p_m_tone != id)
1653         {
1654                 /* set new tone */
1655                 p_m_tone = id;
1656                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1657                 if (p_m_b_index > -1)
1658                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1659                         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);
1660         }
1661         /* turn user-space tones off in cases of no tone OR dsp tone */
1662         Port::set_tone("",NULL);
1663 }
1664
1665
1666 /* MESSAGE_mISDNSIGNAL */
1667 //extern struct lcr_msg *dddebug;
1668 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1669 {
1670         switch(param->mISDNsignal.message)
1671         {
1672                 case mISDNSIGNAL_VOLUME:
1673                 if (p_m_tx_gain != param->mISDNsignal.tx_gain)
1674                 {
1675                         p_m_tx_gain = param->mISDNsignal.tx_gain;
1676                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_tx_gain);
1677                         if (p_m_b_index > -1)
1678                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1679                                 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);
1680                 } else
1681                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rx_gain);
1682                 if (p_m_rx_gain != param->mISDNsignal.rx_gain)
1683                 {
1684                         p_m_rx_gain = param->mISDNsignal.rx_gain;
1685                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rx_gain);
1686                         if (p_m_b_index > -1)
1687                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1688                                 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);
1689                 } else
1690                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rx_gain);
1691                 break;
1692
1693                 case mISDNSIGNAL_CONF:
1694 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1695 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1696                 if (p_m_conf != param->mISDNsignal.conf)
1697                 {
1698                         p_m_conf = param->mISDNsignal.conf;
1699                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1700                         if (p_m_b_index > -1)
1701                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1702                                 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);
1703                 } else
1704                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1705                 /* we must set, even if currently tone forbids conf */
1706                 p_m_conf = param->mISDNsignal.conf;
1707 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1708                 break;
1709
1710                 case mISDNSIGNAL_JOINDATA:
1711                 if (p_m_joindata != param->mISDNsignal.joindata)
1712                 {
1713                         p_m_joindata = param->mISDNsignal.joindata;
1714                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1715                 } else
1716                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1717                 break;
1718                 
1719                 case mISDNSIGNAL_DELAY:
1720                 if (p_m_delay != param->mISDNsignal.delay)
1721                 {
1722                         p_m_delay = param->mISDNsignal.delay;
1723                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1724                         if (p_m_b_index > -1)
1725                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1726                                 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);
1727                 } else
1728                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1729                 break;
1730
1731                 default:
1732                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1733         }
1734 }
1735
1736 /* MESSAGE_CRYPT */
1737 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1738 {
1739         struct lcr_msg *message;
1740
1741         switch(param->crypt.type)
1742         {
1743                 case CC_ACTBF_REQ:           /* activate blowfish */
1744                 p_m_crypt = 1;
1745                 p_m_crypt_key_len = param->crypt.len;
1746                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1747                 {
1748                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1749                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1750                         message->param.crypt.type = CC_ERROR_IND;
1751                         message_put(message);
1752                         break;
1753                 }
1754                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1755                 crypt_off:
1756                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1757                 if (p_m_b_index > -1)
1758                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1759                         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);
1760                 break;
1761
1762                 case CC_DACT_REQ:            /* deactivate session encryption */
1763                 p_m_crypt = 0;
1764                 goto crypt_off;
1765                 break;
1766
1767                 case CR_LISTEN_REQ:          /* start listening to messages */
1768                 p_m_crypt_listen = 1;
1769                 p_m_crypt_listen_state = 0;
1770                 break;
1771
1772                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1773                 p_m_crypt_listen = 0;
1774                 break;
1775
1776                 case CR_MESSAGE_REQ:         /* send message */
1777                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1778                 if (!p_m_crypt_msg_len)
1779                 {
1780                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1781                         break;
1782                 }
1783                 p_m_crypt_msg_current = 0; /* reset */
1784                 p_m_crypt_msg_loops = 6; /* enable */
1785 #if 0
1786                 /* disable txmix, or we get corrupt data due to audio process */
1787                 if (p_m_txmix && p_m_b_index>=0)
1788                 {
1789                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1790                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], DSP_MIX_OFF, 0, "DSP-TXMIX", 0);
1791                 }
1792 #endif
1793                 break;
1794
1795                 default:
1796                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1797         }
1798
1799 }
1800
1801 /*
1802  * endpoint sends messages to the port
1803  */
1804 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1805 {
1806         if (Port::message_epoint(epoint_id, message_id, param))
1807                 return(1);
1808
1809         switch(message_id)
1810         {
1811                 case MESSAGE_DATA: /* tx-data from upper layer */
1812                 txfromup(param->data.data, param->data.len);
1813                 return(1);
1814
1815                 case MESSAGE_mISDNSIGNAL: /* user command */
1816                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1817                 message_mISDNsignal(epoint_id, message_id, param);
1818                 return(1);
1819
1820                 case MESSAGE_CRYPT: /* crypt control command */
1821                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1822                 message_crypt(epoint_id, message_id, param);
1823                 return(1);
1824         }
1825
1826         return(0);
1827 }
1828
1829
1830 /*
1831  * main loop for processing messages from mISDN
1832  */
1833 int mISDN_handler(void)
1834 {
1835         int ret, work = 0;
1836         struct mISDNport *mISDNport;
1837         class PmISDN *isdnport;
1838         int i;
1839         unsigned char buffer[2048+MISDN_HEADER_LEN];
1840         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1841         struct mbuffer *mb;
1842         struct l3_msg *l3m;
1843
1844         /* process all ports */
1845         mISDNport = mISDNport_first;
1846         while(mISDNport)
1847         {
1848                 /* process all bchannels */
1849                 i = 0;
1850                 while(i < mISDNport->b_num)
1851                 {
1852                         /* process timer events for bchannel handling */
1853                         if (mISDNport->b_timer[i])
1854                         {
1855                                 if (mISDNport->b_timer[i] <= now_d)
1856                                         bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
1857                         }
1858                         /* handle port of bchannel */
1859                         isdnport=mISDNport->b_port[i];
1860                         if (isdnport)
1861                         {
1862                                 /* call bridges in user space OR crypto OR recording */
1863                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1864                                 {
1865                                         /* rx IS required */
1866                                         if (isdnport->p_m_rxoff)
1867                                         {
1868                                                 /* turn on RX */
1869                                                 isdnport->p_m_rxoff = 0;
1870                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n", __FUNCTION__);
1871                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1872                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], DSP_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1873                                                 return(1);
1874                                         }
1875                                 } else
1876                                 {
1877                                         /* rx NOT required */
1878                                         if (!isdnport->p_m_rxoff)
1879                                         {
1880                                                 /* turn off RX */
1881                                                 isdnport->p_m_rxoff = 1;
1882                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n", __FUNCTION__);
1883                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1884                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1885                                                 return(1);
1886                                         }
1887                                 }
1888                                 /* recording */
1889                                 if (isdnport->p_record)
1890                                 {
1891                                         /* txdata IS required */
1892                                         if (!isdnport->p_m_txdata)
1893                                         {
1894                                                 /* turn on RX */
1895                                                 isdnport->p_m_txdata = 1;
1896                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n", __FUNCTION__);
1897                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1898                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], DSP_TXDATA_ON, 0, "DSP-TXDATA", 1);
1899                                                 return(1);
1900                                         }
1901                                 } else
1902                                 {
1903                                         /* txdata NOT required */
1904                                         if (isdnport->p_m_txdata)
1905                                         {
1906                                                 /* turn off RX */
1907                                                 isdnport->p_m_txdata = 0;
1908                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n", __FUNCTION__);
1909                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1910                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], DSP_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1911                                                 return(1);
1912                                         }
1913                                 }
1914                         }
1915
1916                         /* handle message from bchannel */
1917                         if (mISDNport->b_socket[i] > -1)
1918                         {
1919                                 ret = recv(mISDNport->b_socket[i], buffer, sizeof(buffer), 0);
1920                                 if (ret >= (int)MISDN_HEADER_LEN)
1921                                 {
1922                                         work = 1;
1923                                         switch(hh->prim)
1924                                         {
1925                                                 /* we don't care about confirms, we use rx data to sync tx */
1926                                                 case PH_DATA_CNF:
1927                                                 break;
1928
1929                                                 /* we receive audio data, we respond to it AND we send tones */
1930                                                 case PH_DATA_IND:
1931                                                 case DL_DATA_IND:
1932                                                 case PH_DATA_REQ:
1933                                                 case DL_DATA_REQ:
1934                                                 case PH_CONTROL_IND:
1935                                                 if (mISDNport->b_port[i])
1936                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1937                                                 else
1938                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_socket[i]);
1939                                                 break;
1940
1941                                                 case PH_ACTIVATE_IND:
1942                                                 case DL_ESTABLISH_IND:
1943                                                 case PH_ACTIVATE_CNF:
1944                                                 case DL_ESTABLISH_CNF:
1945                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
1946                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
1947                                                 break;
1948
1949                                                 case PH_DEACTIVATE_IND:
1950                                                 case DL_RELEASE_IND:
1951                                                 case PH_DEACTIVATE_CNF:
1952                                                 case DL_RELEASE_CNF:
1953                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
1954                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
1955                                                 break;
1956
1957                                                 default:
1958                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], ret-MISDN_HEADER_LEN);
1959                                         }
1960                                 } else
1961                                 {
1962                                         if (ret < 0 && errno != EWOULDBLOCK)
1963                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
1964                                 }
1965                         }
1966                         
1967                         i++;
1968                 }
1969
1970                 /* handle queued up-messages (d-channel) */
1971                 while ((mb = mdequeue(&mISDNport->upqueue)))
1972                 {
1973                         l3m = &mb->l3;
1974                         switch(l3m->type)
1975                         {
1976                                 case MPH_ACTIVATE_IND:
1977                                 l1l2l3_trace_header(mISDNport, NULL, L1_ACTIVATE_IND, DIRECTION_IN);
1978                                 end_trace();
1979                                 mISDNport->l1link = 1;
1980                                 break;
1981         
1982                                 case MPH_DEACTIVATE_IND:
1983                                 l1l2l3_trace_header(mISDNport, NULL, L1_DEACTIVATE_IND, DIRECTION_IN);
1984                                 end_trace();
1985                                 mISDNport->l1link = 0;
1986                                 break;
1987
1988                                 case MPH_INFORMATION_IND:
1989                                 PDEBUG(DEBUG_ISDN, "Received MPH_INFORMATION_IND for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
1990                                 switch (l3m->pid)
1991                                 {
1992                                         case L1_SIGNAL_LOS_ON:
1993                                         mISDNport->los = 1;
1994                                         break;
1995                                         case L1_SIGNAL_LOS_OFF:
1996                                         mISDNport->los = 0;
1997                                         break;
1998                                         case L1_SIGNAL_AIS_ON:
1999                                         mISDNport->ais = 1;
2000                                         break;
2001                                         case L1_SIGNAL_AIS_OFF:
2002                                         mISDNport->ais = 0;
2003                                         break;
2004                                         case L1_SIGNAL_RDI_ON:
2005                                         mISDNport->rdi = 1;
2006                                         break;
2007                                         case L1_SIGNAL_RDI_OFF:
2008                                         mISDNport->rdi = 0;
2009                                         break;
2010                                         case L1_SIGNAL_SLIP_TX:
2011                                         mISDNport->slip_tx++;
2012                                         break;
2013                                         case L1_SIGNAL_SLIP_RX:
2014                                         mISDNport->slip_rx++;
2015                                         break;
2016                                 }
2017                                 break;
2018
2019                                 case MT_L2ESTABLISH:
2020                                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_IND, DIRECTION_IN);
2021                                 add_trace("tei", NULL, "%d", l3m->pid);
2022                                 end_trace();
2023                                 if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
2024                                 {
2025                                         if (mISDNport->l2establish)
2026                                         {
2027                                                 mISDNport->l2establish = 0;
2028                                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2029                                         }
2030                                         mISDNport->l2link = 1;
2031                                 }
2032                                 break;
2033
2034                                 case MT_L2RELEASE:
2035                                 l1l2l3_trace_header(mISDNport, NULL, L2_RELEASE_IND, DIRECTION_IN);
2036                                 add_trace("tei", NULL, "%d", l3m->pid);
2037                                 end_trace();
2038                                 if ((!mISDNport->ntmode || mISDNport->ptp) && l3m->pid < 127)
2039                                 {
2040                                         mISDNport->l2link = 0;
2041                                         if (mISDNport->l2hold)
2042                                         {
2043                                                 time(&mISDNport->l2establish);
2044                                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2045                                         }
2046                                 }
2047                                 break;
2048
2049                                 default:
2050                                 /* l3-data is sent to LCR */
2051                                 stack2manager(mISDNport, l3m->type, l3m->pid, l3m);
2052                         }
2053                         /* free message */
2054                         free_l3_msg(l3m);
2055                 }
2056
2057 #if 0
2058                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2059                 { ---}
2060                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2061                         mISDNport->l1timeout = 0;
2062 #endif
2063
2064                 /* layer 2 establish timer */
2065                 if (mISDNport->l2establish)
2066                 {
2067                         if (now-mISDNport->l2establish > 5)
2068                         {
2069                                 mISDNport->l2establish = 0;
2070                                 if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2071                                 {
2072
2073                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2074                                         mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2075                                         l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2076                                         add_trace("tei", NULL, "%d", 0);
2077                                         end_trace();
2078                                         time(&mISDNport->l2establish);
2079                                         return(1);
2080                                 }
2081                         }
2082                 }
2083
2084
2085                 mISDNport = mISDNport->next;
2086         }
2087
2088         /* if we received at least one b-frame, we will return 1 */
2089         return(work);
2090 }
2091
2092 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2093 {
2094         /* IMPORTAINT:
2095          *
2096          * l3m must be queued, except for MT_ASSIGN
2097          *
2098          */
2099         struct mISDNport *mISDNport = (struct mISDNport *)ml3->priv;
2100         struct mbuffer *mb;
2101
2102         /* special MT_ASSIGN handling:
2103          *
2104          * if we request a PID from mlayer, we always do it while lcr is locked.
2105          * therefore we must check the MT_ASSIGN reply first before we lock.
2106          * this is because the MT_ASSIGN reply is received with the requesting
2107          * process, not by the mlayer thread!
2108          * this means, that the reply is sent during call of the request.
2109          * we must check if we get a reply and we know that we lcr is currently
2110          * locked.
2111          */
2112         if (cmd==MT_ASSIGN && (pid&MISDN_PID_CR_FLAG) && (pid>>16)==MISDN_CES_MASTER)
2113         {
2114                 /* let's do some checking if someone changes stack behaviour */
2115                 if (mt_assign_pid != 0)
2116                         FATAL("someone played with the mISDNuser stack. MT_ASSIGN not currently expected.\n");
2117                 mt_assign_pid = pid;
2118                 return(0);
2119         }
2120         
2121         /* queue message, create, if required */
2122         if (!l3m)
2123         {
2124                 l3m = alloc_l3_msg();
2125                 if (!l3m)
2126                         FATAL("No memory for layer 3 message\n");
2127         }
2128         mb = container_of(l3m, struct mbuffer, l3);
2129         l3m->type = cmd;
2130         l3m->pid = pid;
2131         mqueue_tail(&mISDNport->upqueue, mb);
2132         return 0;
2133 }
2134
2135
2136 /*
2137  * global function to add a new card (port)
2138  */
2139 struct mISDNport *mISDNport_open(int port, int ptp, int force_nt, int l2hold, struct interface *interface)
2140 {
2141         int ret;
2142         struct mISDNport *mISDNport, **mISDNportp;
2143         int i, cnt;
2144         int pri, bri, pots;
2145         int nt, te;
2146 //      struct mlayer3 *ml3;
2147         struct mISDN_devinfo devinfo;
2148         unsigned int protocol, prop;
2149
2150         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2151         if (ret < 0)
2152         {
2153                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2154                 return(NULL);
2155         }
2156
2157         if (cnt <= 0)
2158         {
2159                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2160                 return(NULL);
2161         }
2162         if (port>cnt || port<1)
2163         {
2164                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2165                 return(NULL);
2166         }
2167
2168         pri = bri = pots = nt = te = 0;
2169         devinfo.id = port - 1;
2170         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
2171         if (ret < 0)
2172         {
2173                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2174                 return(NULL);
2175         }
2176         /* output the port info */
2177         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2178         {
2179                 bri = 1;
2180                 te = 1;
2181         }
2182         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2183         {
2184                 bri = 1;
2185                 nt = 1;
2186         }
2187         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2188         {
2189                 pri = 1;
2190                 te = 1;
2191         }
2192         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2193         {
2194                 pri = 1;
2195                 nt = 1;
2196         }
2197 #ifdef ISDN_P_FXS
2198         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2199         {
2200                 pots = 1;
2201                 te = 1;
2202         }
2203 #endif
2204 #ifdef ISDN_P_FXO
2205         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2206         {
2207                 pots = 1;
2208                 nt = 1;
2209         }
2210 #endif
2211         if (force_nt && !nt)
2212         {
2213                 PERROR_RUNTIME("Port %d does not support NT-mode\n", port);
2214                 return(NULL);
2215         }
2216         if (bri && pri)
2217         {
2218                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2219                 return(NULL);
2220         }
2221         if (pots && !bri && !pri)
2222         {
2223                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2224                 return(NULL);
2225         }
2226         if (!bri && !pri)
2227         {
2228                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2229                 return(NULL);
2230         }
2231         if (!nt && !te)
2232         {
2233                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2234                 return(NULL);
2235         }
2236         /* set NT by turning off TE */
2237         if (force_nt && nt)
2238                 te = 0;
2239         /* if TE an NT is supported (and not forced to NT), turn off NT */
2240         if (te && nt)
2241                 nt = 0;
2242
2243         /* add mISDNport structure */
2244         mISDNportp = &mISDNport_first;
2245         while(*mISDNportp)
2246                 mISDNportp = &((*mISDNportp)->next);
2247         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2248         pmemuse++;
2249         *mISDNportp = mISDNport;
2250
2251         /* if pri, must set PTP */
2252         if (pri)
2253                 ptp = 1;
2254         
2255         /* set l2hold */
2256         switch (l2hold)
2257         {
2258                 case -1: // off
2259                 l2hold = 0;
2260                 break;
2261                 case 1: // on
2262                 l2hold = 1;
2263                 break;
2264                 default:
2265                 if (ptp)
2266                         l2hold = 1;
2267                 else
2268                         l2hold = 0;
2269                 break;
2270         }
2271                 
2272         /* allocate ressources of port */
2273         /* open layer 3 and init upqueue */
2274         protocol = (nt)?L3_PROTOCOL_DSS1_NET:L3_PROTOCOL_DSS1_USER;
2275         prop = (1 << MISDN_FLG_L2_CLEAN);
2276         if (ptp) // ptp forced
2277                prop |= (1 << MISDN_FLG_PTP);
2278         if (nt) // supports hold/retrieve on nt-mode
2279                prop |= (1 << MISDN_FLG_NET_HOLD);
2280         if (l2hold) // supports layer 2 hold
2281                prop |= (1 << MISDN_FLG_L2_HOLD);
2282         /* queue must be initializes, because l3-thread may send messages during open_layer3() */
2283         mqueue_init(&mISDNport->upqueue);
2284         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_layer3, mISDNport);
2285         if (!mISDNport->ml3)
2286         {
2287                 mqueue_purge(&mISDNport->upqueue);
2288                 PERROR_RUNTIME("open_layer3() failed for port %d\n", port);
2289                 start_trace(port,
2290                         interface,
2291                         NULL,
2292                         NULL,
2293                         DIRECTION_NONE,
2294                         CATEGORY_CH,
2295                         0,
2296                         "PORT (open failed)");
2297                 end_trace();
2298                 mISDNport_close(mISDNport);
2299                 return(NULL);
2300         }
2301
2302 #if 0
2303         /* if ntmode, establish L1 to send the tei removal during start */
2304         if (mISDNport->ntmode)
2305         {
2306                 iframe_t act;
2307                 /* L1 */
2308                 act.prim = PH_ACTIVATE | REQUEST; 
2309                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2310                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2311                 act.dinfo = 0;
2312                 act.len = 0;
2313                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2314                 usleep(10000); /* to be sure, that l1 is up */
2315         }
2316 #endif
2317
2318         SCPY(mISDNport->name, devinfo.name);
2319         mISDNport->b_num = devinfo.nrbchan;
2320         mISDNport->portnum = port;
2321         mISDNport->ntmode = nt;
2322         mISDNport->pri = pri;
2323         mISDNport->ptp = ptp;
2324         mISDNport->l2hold = l2hold;
2325         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
2326         i = 0;
2327         while(i < mISDNport->b_num)
2328         {
2329                 mISDNport->b_state[i] = B_STATE_IDLE;
2330                 mISDNport->b_socket[i] = -1;
2331                 i++;
2332         }
2333
2334         /* if ptp, pull up the link */
2335         if (mISDNport->l2hold && (mISDNport->ptp || !mISDNport->ntmode))
2336         {
2337                 mISDNport->ml3->to_layer3(mISDNport->ml3, MT_L2ESTABLISH, 0, NULL);
2338                 l1l2l3_trace_header(mISDNport, NULL, L2_ESTABLISH_REQ, DIRECTION_OUT);
2339                 add_trace("tei", NULL, "%d", 0);
2340                 end_trace();
2341                 time(&mISDNport->l2establish);
2342         }
2343
2344         /* initially, we assume that the link is down, exept for nt-ptmp */
2345         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2346
2347         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2348
2349         start_trace(mISDNport->portnum,
2350                     interface,
2351                     NULL,
2352                     NULL,
2353                     DIRECTION_NONE,
2354                     CATEGORY_CH,
2355                     0,
2356                     "PORT (open)");
2357         add_trace("mode", NULL, (mISDNport->ntmode)?"network":"terminal");
2358         add_trace("channels", NULL, "%d", mISDNport->b_num);
2359         end_trace();
2360         return(mISDNport);
2361 }
2362
2363
2364 /*
2365  * function to free ALL cards (ports)
2366  */
2367 void mISDNport_close_all(void)
2368 {
2369         /* free all ports */
2370         while(mISDNport_first)
2371                 mISDNport_close(mISDNport_first);
2372 }
2373
2374 /*
2375  * free only one port
2376  */
2377 void mISDNport_close(struct mISDNport *mISDNport)
2378 {
2379         struct mISDNport **mISDNportp;
2380         class Port *port;
2381         class PmISDN *isdnport;
2382         int i;
2383
2384         /* remove all port instance that are linked to this mISDNport */
2385         port = port_first;
2386         while(port)
2387         {
2388                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2389                 {
2390                         isdnport = (class PmISDN *)port;
2391                         if (isdnport->p_m_mISDNport)
2392                         {
2393                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2394                                 delete isdnport;
2395                         }
2396                 }
2397                 port = port->next;
2398         }
2399
2400         /* only if we are already part of interface */
2401         if (mISDNport->ifport)
2402         {
2403                 start_trace(mISDNport->portnum,
2404                             mISDNport->ifport->interface,
2405                             NULL,
2406                             NULL,
2407                             DIRECTION_NONE,
2408                             CATEGORY_CH,
2409                             0,
2410                             "PORT (close)");
2411                 end_trace();
2412         }
2413
2414         /* free bchannels */
2415         i = 0;
2416         while(i < mISDNport->b_num)
2417         {
2418                 if (mISDNport->b_socket[i] > -1)
2419                 {
2420                         _bchannel_destroy(mISDNport, i);
2421                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2422                 }
2423                 i++;
2424         }
2425
2426         /* close layer 3, if open and purge upqueue */
2427         if (mISDNport->ml3)
2428         {
2429                 close_layer3(mISDNport->ml3);
2430                 mqueue_purge(&mISDNport->upqueue);
2431         }
2432
2433         /* remove from list */
2434         mISDNportp = &mISDNport_first;
2435         while(*mISDNportp)
2436         {
2437                 if (*mISDNportp == mISDNport)
2438                 {
2439                         *mISDNportp = (*mISDNportp)->next;
2440                         mISDNportp = NULL;
2441                         break;
2442                 }
2443                 mISDNportp = &((*mISDNportp)->next);
2444         }
2445
2446         if (mISDNportp)
2447                 FATAL("mISDNport not in list\n");
2448         
2449         FREE(mISDNport, sizeof(struct mISDNport));
2450         pmemuse--;
2451
2452 }
2453
2454
2455 /*
2456  * global function to show all available isdn ports
2457  */
2458 void mISDN_port_info(void)
2459 {
2460         int ret;
2461         int i, ii;
2462         int useable, nt, te, pri, bri, pots;
2463         struct mISDN_devinfo devinfo;
2464         int sock;
2465
2466         /* open mISDN */
2467         sock = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
2468         if (sock < 0)
2469         {
2470                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
2471                 exit(EXIT_FAILURE);
2472         }
2473
2474         /* get number of stacks */
2475         i = 1;
2476         ret = ioctl(sock, IMGETCOUNT, &ii);
2477         if (ret < 0)
2478         {
2479                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2480                 goto done;
2481         }
2482         printf("\n");
2483         if (ii <= 0)
2484         {
2485                 printf("Found no card. Please be sure to load card drivers.\n");
2486                 goto done;
2487         }
2488
2489         /* loop the number of cards and get their info */
2490         while(i <= ii)
2491         {
2492                 nt = te = bri = pri = pots = 0;
2493                 useable = 0;
2494
2495                 devinfo.id = i - 1;
2496                 ret = ioctl(sock, IMGETDEVINFO, &devinfo);
2497                 if (ret < 0)
2498                 {
2499                         fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2500                         break;
2501                 }
2502
2503                 /* output the port info */
2504                 printf("Port %2d name='%s': ", i, devinfo.name);
2505                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2506                 {
2507                         bri = 1;
2508                         te = 1;
2509                 }
2510                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2511                 {
2512                         bri = 1;
2513                         nt = 1;
2514                 }
2515                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2516                 {
2517                         pri = 1;
2518                         te = 1;
2519                 }
2520                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2521                 {
2522                         pri = 1;
2523                         nt = 1;
2524                 }
2525 #ifdef ISDN_P_FXS
2526                 if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2527                 {
2528                         pots = 1;
2529                         te = 1;
2530                 }
2531 #endif
2532 #ifdef ISDN_P_FXO
2533                 if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2534                 {
2535                         pots = 1;
2536                         nt = 1;
2537                 }
2538 #endif
2539                 if ((te || nt) && (bri || pri || pots))
2540                         useable = 1;
2541
2542                 if (te && nt && bri)
2543                         printf("TE/NT-mode BRI S/T (for phone lines & phones)");
2544                 if (te && !nt && bri)
2545                         printf("TE-mode    BRI S/T (for phone lines)");
2546                 if (nt && !te && bri)
2547                         printf("NT-mode    BRI S/T (for phones)");
2548                 if (te && nt && pri)
2549                         printf("TE/NT-mode PRI E1  (for phone lines & E1 devices)");
2550                 if (te && !nt && pri)
2551                         printf("TE-mode    PRI E1  (for phone lines)");
2552                 if (nt && !te && pri)
2553                         printf("NT-mode    PRI E1  (for E1 devices)");
2554                 if (te && nt && pots)
2555                         printf("FXS/FXO    POTS    (for analog lines & phones)");
2556                 if (te && !nt && pots)
2557                         printf("FXS        POTS    (for analog lines)");
2558                 if (nt && !te && pots)
2559                         printf("FXO        POTS    (for analog phones)");
2560                 if (pots)
2561                 {
2562                         useable = 0;
2563                         printf("\n -> Analog interfaces are not supported.");
2564                 } else
2565                 if (!useable)
2566                 {
2567                         printf("unsupported interface protocol bits 0x%016x", devinfo.Dprotocols);
2568                 }
2569                 printf("\n");
2570
2571                 printf("  - %d B-channels\n", devinfo.nrbchan);
2572
2573                 if (!useable)
2574                         printf(" * Port NOT useable for LCR\n");
2575
2576                 printf("--------\n");
2577
2578                 i++;
2579         }
2580         printf("\n");
2581
2582 done:
2583         close(sock);
2584 }
2585
2586
2587 /*
2588  * enque data from upper buffer
2589  */
2590 void PmISDN::txfromup(unsigned char *data, int length)
2591 {
2592         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2593         struct mISDNhead *hh = (struct mISDNhead *)buf;
2594         int ret;
2595
2596         if (p_m_b_index < 0)
2597                 return;
2598         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_ACTIVE)
2599                 return;
2600
2601         /* check if high priority tones exist
2602          * ignore data in this case
2603          */
2604         if (p_tone_name[0] || p_m_crypt_msg_loops)
2605                 return;
2606
2607         /* preload procedure
2608          * if transmit buffer in DSP module is empty,
2609          * preload it to DSP_LOAD to prevent jitter gaps.
2610          */
2611         if (p_m_load==0 && ISDN_LOAD>0)
2612         {
2613                 hh->prim = PH_DATA_REQ; 
2614                 hh->id = 0;
2615                 memset(buf+MISDN_HEADER_LEN, (options.law=='a')?0x2a:0xff, ISDN_LOAD);
2616                 ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+ISDN_LOAD, 0, NULL, 0);
2617                 if (ret <= 0)
2618                         PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2619                 p_m_load += ISDN_LOAD;
2620         }
2621
2622         /* drop if load would exceed ISDN_MAXLOAD
2623          * this keeps the delay not too high
2624          */
2625         if (p_m_load+length > ISDN_MAXLOAD)
2626                 return;
2627
2628         /* make and send frame */
2629         hh->prim = PH_DATA_REQ;
2630         hh->id = 0;
2631         memcpy(buf+MISDN_HEADER_LEN, data, length);
2632         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
2633         if (ret <= 0)
2634                 PERROR("Failed to send to socket %d\n", p_m_mISDNport->b_socket[p_m_b_index]);
2635         p_m_load += length;
2636 }
2637