Added keypad forwarding, keypad parameter, chan_lcr keypad option 'k'.
[lcr.git] / bchannel.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN channel handlin for remote application                              **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <poll.h>
17 #include <errno.h>
18 #include <sys/ioctl.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #include <netinet/udp.h>
23 #include <netinet/in.h>
24 #include <netdb.h>
25 #include <sys/socket.h>
26 #include <mISDNif.h>
27
28 #define AF_COMPATIBILITY_FUNC 1
29 #define MISDN_OLD_AF_COMPATIBILITY 1
30 #include <compat_af_isdn.h>
31
32 #define HAVE_ATTRIBUTE_always_inline 1
33 #define HAVE_ARPA_INET_H 1
34 #define HAVE_TIMERSUB 1
35
36 #include <asterisk/compiler.h>
37 #include <asterisk/frame.h>
38
39 /* Choose if you want to have chan_lcr for Asterisk 1.4.x or CallWeaver 1.2.x */
40 /* #define LCR_FOR_CALLWEAVER */
41
42 #ifdef LCR_FOR_CALLWEAVER
43 #include <asterisk/phone_no_utils.h>
44 #include <asterisk/logger.h>
45 #include <asterisk/module.h>
46 #include <asterisk/channel.h>
47 #endif
48
49 #include "extension.h"
50 #include "message.h"
51 #include "lcrsocket.h"
52 #include "cause.h"
53 #include "bchannel.h"
54 #include "chan_lcr.h"
55 #include "callerid.h"
56
57
58 #ifndef ISDN_PID_L4_B_USER
59 #define ISDN_PID_L4_B_USER 0x440000ff
60 #endif
61
62 pid_t   bchannel_pid;
63
64 enum {
65         BSTATE_IDLE,
66         BSTATE_ACTIVATING,
67         BSTATE_ACTIVE,
68         BSTATE_DEACTIVATING,
69 };
70
71
72 int bchannel_initialize(void)
73 {
74         init_af_isdn();
75
76         return(0);
77 }
78
79 void bchannel_deinitialize(void)
80 {
81 }
82
83 /*
84  * send control information to the channel (dsp-module)
85  */
86 static void ph_control(int sock, unsigned int c1, unsigned int c2, char *trace_name, int trace_value, int b_mode)
87 {
88         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
89         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
90         unsigned int *d = (unsigned int *)(buffer+MISDN_HEADER_LEN);
91         int ret;
92
93         if (b_mode != 0 && b_mode != 2)
94                 return;
95
96         CDEBUG(NULL, NULL, "Sending PH_CONTROL %s %x,%x\n", trace_name, c1, c2);
97         ctrl->prim = PH_CONTROL_REQ;
98         ctrl->id = 0;
99         *d++ = c1;
100         *d++ = c2;
101         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
102         if (ret < 0)
103                 CERROR(NULL, NULL, "Failed to send to socket %d\n", sock);
104 }
105
106 static void ph_control_block(int sock, unsigned int c1, void *c2, int c2_len, char *trace_name, int trace_value, int b_mode)
107 {
108         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
109         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
110         unsigned int *d = (unsigned int *)(buffer+MISDN_HEADER_LEN);
111         int ret;
112
113         if (b_mode != 0 && b_mode != 2)
114                 return;
115
116         CDEBUG(NULL, NULL, "Sending PH_CONTROL (block) %s %x\n", trace_name, c1);
117         ctrl->prim = PH_CONTROL_REQ;
118         ctrl->id = 0;
119         *d++ = c1;
120         memcpy(d, c2, c2_len);
121         ret = sendto(sock, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
122         if (ret < 0)
123                 CERROR(NULL, NULL, "Failed to send to socket %d\n", sock);
124 }
125
126
127 /*
128  * create stack
129  */
130 int bchannel_create(struct bchannel *bchannel, int mode)
131 {
132         int ret;
133         unsigned int on = 1;
134         struct sockaddr_mISDN addr;
135
136         if (bchannel->b_sock > -1) {
137                 CERROR(bchannel->call, NULL, "Socket already created for handle 0x%x\n", bchannel->handle);
138                 return(0);
139         }
140
141         /* open socket */
142         bchannel->b_mode = mode;
143         switch(bchannel->b_mode) {
144                 case 0:
145                 CDEBUG(bchannel->call, NULL, "Open DSP audio\n");
146                 bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
147                 break;
148                 case 1:
149                 CDEBUG(bchannel->call, NULL, "Open audio\n");
150                 bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
151                 break;
152                 case 2:
153                 CDEBUG(bchannel->call, NULL, "Open DSP HDLC\n");
154                 bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSPHDLC);
155                 break;
156                 case 3:
157                 CDEBUG(bchannel->call, NULL, "Open HDLC\n");
158                 bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_HDLC);
159                 break;
160         }
161         if (bchannel->b_sock < 0) {
162                 CERROR(bchannel->call, NULL, "Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDN_dsp.ko?\n", bchannel->handle);
163                 return(0);
164         }
165         
166         /* set nonblocking io */
167         ret = ioctl(bchannel->b_sock, FIONBIO, &on);
168         if (ret < 0) {
169                 CERROR(bchannel->call, NULL, "Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
170                 close(bchannel->b_sock);
171                 bchannel->b_sock = -1;
172                 return(0);
173         }
174
175         /* bind socket to bchannel */
176         addr.family = AF_ISDN;
177         addr.dev = (bchannel->handle>>8);
178         addr.channel = bchannel->handle & 0xff;
179         ret = bind(bchannel->b_sock, (struct sockaddr *)&addr, sizeof(addr));
180         if (ret < 0) {
181                 CERROR(bchannel->call, NULL, "Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. (port %d, channel %d) Did you load mISDN_dsp.ko?\n", bchannel->handle, addr.dev, addr.channel);
182                 close(bchannel->b_sock);
183                 bchannel->b_sock = -1;
184                 return(0);
185         }
186         return(1);
187 }
188
189
190 /*
191  * activate / deactivate request
192  */
193 void bchannel_activate(struct bchannel *bchannel, int activate)
194 {
195         struct mISDNhead act;
196         int ret;
197
198         /* activate bchannel */
199         CDEBUG(bchannel->call, NULL, "%sActivating B-channel.\n", activate?"":"De-");
200         switch(bchannel->b_mode) {
201                 case 0:
202                 case 2:
203                 act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ; 
204                 break;
205                 case 1:
206                 case 3:
207                 act.prim = (activate)?PH_ACTIVATE_REQ:PH_DEACTIVATE_REQ; 
208                 break;
209         }
210         act.id = 0;
211         ret = sendto(bchannel->b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
212         if (ret < 0)
213                 CERROR(bchannel->call, NULL, "Failed to send to socket %d\n", bchannel->b_sock);
214
215         bchannel->b_state = (activate)?BSTATE_ACTIVATING:BSTATE_DEACTIVATING;
216 }
217
218
219 /*
220  * set features
221  */
222 static void bchannel_activated(struct bchannel *bchannel)
223 {
224         int sock;
225
226         sock = bchannel->b_sock;
227
228         /* set dsp features */
229         if (bchannel->b_txdata)
230                 ph_control(sock, (bchannel->b_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", bchannel->b_txdata, bchannel->b_mode);
231         if (bchannel->b_delay && bchannel->b_mode == 0)
232                 ph_control(sock, DSP_DELAY, bchannel->b_delay, "DSP-DELAY", bchannel->b_delay, bchannel->b_mode);
233         if (bchannel->b_tx_dejitter && bchannel->b_mode == 0)
234                 ph_control(sock, (bchannel->b_tx_dejitter)?DSP_TX_DEJITTER:DSP_TX_DEJ_OFF, 0, "DSP-TX_DEJITTER", bchannel->b_tx_dejitter, bchannel->b_mode);
235         if (bchannel->b_tx_gain && bchannel->b_mode == 0)
236                 ph_control(sock, DSP_VOL_CHANGE_TX, bchannel->b_tx_gain, "DSP-TX_GAIN", bchannel->b_tx_gain, bchannel->b_mode);
237         if (bchannel->b_rx_gain && bchannel->b_mode == 0)
238                 ph_control(sock, DSP_VOL_CHANGE_RX, bchannel->b_rx_gain, "DSP-RX_GAIN", bchannel->b_rx_gain, bchannel->b_mode);
239         if (bchannel->b_pipeline[0] && bchannel->b_mode == 0)
240                 ph_control_block(sock, DSP_PIPELINE_CFG, bchannel->b_pipeline, strlen(bchannel->b_pipeline)+1, "DSP-PIPELINE", 0, bchannel->b_mode);
241         if (bchannel->b_conf)
242                 ph_control(sock, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf, bchannel->b_mode);
243         if (bchannel->b_echo)
244                 ph_control(sock, DSP_ECHO_ON, 0, "DSP-ECHO", 1, bchannel->b_mode);
245         if (bchannel->b_tone && bchannel->b_mode == 0)
246                 ph_control(sock, DSP_TONE_PATT_ON, bchannel->b_tone, "DSP-TONE", bchannel->b_tone, bchannel->b_mode);
247         if (bchannel->b_rxoff)
248                 ph_control(sock, DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1, bchannel->b_mode);
249 //      if (bchannel->b_txmix && bchannel->b_mode == 0)
250 //              ph_control(sock, DSP_MIX_ON, 0, "DSP-MIX", 1, bchannel->b_mode);
251         if (bchannel->b_dtmf && bchannel->b_mode == 0)
252                 ph_control(sock, DTMF_TONE_START, 0, "DSP-DTMF", 1, bchannel->b_mode);
253         if (bchannel->b_bf_len && bchannel->b_mode == 0)
254                 ph_control_block(sock, DSP_BF_ENABLE_KEY, bchannel->b_bf_key, bchannel->b_bf_len, "DSP-CRYPT", bchannel->b_bf_len, bchannel->b_mode);
255         if (bchannel->b_conf)
256                 ph_control(sock, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf, bchannel->b_mode);
257
258         bchannel->b_state = BSTATE_ACTIVE;
259 }
260
261 /*
262  * destroy stack
263  */
264 void bchannel_destroy(struct bchannel *bchannel)
265 {
266         if (bchannel->b_sock > -1) {
267                 close(bchannel->b_sock);
268                 bchannel->b_sock = -1;
269         }
270         bchannel->b_state = BSTATE_IDLE;
271 }
272
273
274 /*
275  * whenever we get audio data from bchannel, we process it here
276  */
277 static void bchannel_receive(struct bchannel *bchannel, unsigned char *buffer, int len)
278 {
279         struct mISDNhead *hh = (struct mISDNhead *)buffer;
280         unsigned char *data = buffer + MISDN_HEADER_LEN;
281         unsigned int cont = *((unsigned int *)data);
282         unsigned char *d;
283         int i;
284         struct bchannel *remote_bchannel;
285         int ret;
286
287         if (hh->prim == PH_CONTROL_IND) {
288                 /* non dsp -> ignore ph_control */
289                 if (bchannel->b_mode == 1 || bchannel->b_mode == 3)
290                         return;
291                 if (len < 4) {
292                         CERROR(bchannel->call, NULL, "SHORT READ OF PH_CONTROL INDICATION\n");
293                         return;
294                 }
295                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
296                         if (bchannel->call)
297                                 lcr_in_dtmf(bchannel->call, cont & DTMF_TONE_MASK);
298                         return;
299                 }
300                 switch(cont) {
301                         case DSP_BF_REJECT:
302                         CERROR(bchannel->call, NULL, "Blowfish crypt rejected.\n");
303                         break;
304
305                         case DSP_BF_ACCEPT:
306                         CDEBUG(bchannel->call, NULL, "Blowfish crypt enabled.\n");
307                         break;
308
309                         default:
310                         CDEBUG(bchannel->call, NULL, "Unhandled bchannel control 0x%x.\n", cont);
311                 }
312                 return;
313         }
314         if (hh->prim == PH_DATA_REQ) {
315                 if (!bchannel->b_txdata) {
316                         /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
317                         CDEBUG(bchannel->call, NULL, "ignoring tx data, because 'txdata' is turned off\n");
318                         return;
319                 }
320                 return;
321         }
322         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND) {
323                 CERROR(bchannel->call, NULL, "Bchannel received unknown primitve: 0x%lx\n", hh->prim);
324                 return;
325         }
326         /* if calls are bridged, but not via dsp (no b_conf), forward here */
327         if (!bchannel->b_conf
328          && bchannel->call
329          && bchannel->call->bridge_call
330          && bchannel->call->bridge_call->bchannel) {
331                 remote_bchannel = bchannel->call->bridge_call->bchannel;
332 #if 0
333                 int i = 0;
334                 char string[4096] = "";
335                 while(i < len) {
336                         sprintf(string+strlen(string), " %02x", data[i]);
337                         i++;
338                 }
339                 CDEBUG(remote_bchannel->call, NULL, "Forwarding packet%s\n", string);
340 #endif
341                 hh->prim = PH_DATA_REQ;
342                 hh->id = 0;
343                 ret = sendto(remote_bchannel->b_sock, buffer, MISDN_HEADER_LEN+len, 0, NULL, 0);
344                 if (ret < 0)
345                         CERROR(remote_bchannel->call, NULL, "Failed to send to socket %d\n", bchannel->b_sock);
346                 return;
347         }
348         /* calls will not process any audio data unless
349          * the call is connected OR interface features audio during call setup.
350          */
351
352         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
353         if (bchannel->b_rxoff) {
354                 CDEBUG(bchannel->call, NULL, "ignoring data, because rx is turned off\n");
355                 return;
356         }
357
358         if (!bchannel->call) {
359                 CDEBUG(bchannel->call, NULL, "ignoring data, because no call associated with bchannel\n");
360                 return;
361         }
362         if (!bchannel->call->audiopath) {
363                 /* return, because we have no audio from port */
364                 return;
365         }
366
367         if (bchannel->call->pipe[1] < 0) {
368                 /* nobody there */
369                 return;
370         }
371
372         /* if no hdlc */
373         if (bchannel->b_mode == 0 || bchannel->b_mode == 1) {
374                 d = data;
375                 for (i = 0; i < len; i++) {
376                         *d = flip_bits[*d];
377                         d++;
378                 }
379         }
380
381         
382         len = write(bchannel->call->pipe[1], data, len);
383         if (len < 0)
384                 goto errout;
385
386         return;
387  errout:
388         close(bchannel->call->pipe[1]);
389         bchannel->call->pipe[1] = -1;
390         CDEBUG(bchannel->call, NULL, "broken pipe on bchannel pipe\n");
391 }
392
393
394 /*
395  * transmit data to bchannel
396  */
397 void bchannel_transmit(struct bchannel *bchannel, unsigned char *data, int len)
398 {
399         unsigned char buff[1024 + MISDN_HEADER_LEN], *p = buff + MISDN_HEADER_LEN;
400         struct mISDNhead *frm = (struct mISDNhead *)buff;
401         int ret;
402         int i;
403
404         if (bchannel->b_state != BSTATE_ACTIVE)
405                 return;
406         if (len > 1024 || len < 1)
407                 return;
408         switch(bchannel->b_mode) {
409         case 0:
410                 for (i = 0; i < len; i++)
411                         *p++ = flip_bits[*data++];
412                 frm->prim = DL_DATA_REQ;
413                 break;
414         case 1:
415                 for (i = 0; i < len; i++)
416                         *p++ = flip_bits[*data++];
417                 frm->prim = PH_DATA_REQ;
418                 break;
419         case 2:
420                 memcpy(p, data, len);
421                 frm->prim = DL_DATA_REQ;
422                 break;
423         case 3:
424                 memcpy(p, data, len);
425                 frm->prim = PH_DATA_REQ;
426                 break;
427         }
428         frm->id = 0;
429         ret = sendto(bchannel->b_sock, buff, MISDN_HEADER_LEN+len, 0, NULL, 0);
430         if (ret < 0)
431                 CERROR(bchannel->call, NULL, "Failed to send to socket %d\n", bchannel->b_sock);
432 }
433
434
435 /*
436  * join bchannel
437  */
438 void bchannel_join(struct bchannel *bchannel, unsigned short id)
439 {
440         int sock;
441
442         sock = bchannel->b_sock;
443         if (id) {
444                 bchannel->b_conf = (id<<16) + bchannel_pid;
445                 bchannel->b_rxoff = 1;
446         } else {
447                 bchannel->b_conf = 0;
448                 bchannel->b_rxoff = 0;
449         }
450         if (bchannel->b_state == BSTATE_ACTIVE) {
451                 ph_control(sock, DSP_RECEIVE_OFF, bchannel->b_rxoff, "DSP-RX_OFF", bchannel->b_conf, bchannel->b_mode);
452                 ph_control(sock, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf, bchannel->b_mode);
453         }
454 }
455
456
457 /*
458  * dtmf bchannel
459  */
460 void bchannel_dtmf(struct bchannel *bchannel, int on)
461 {
462         int sock;
463
464         sock = bchannel->b_sock;
465         bchannel->b_dtmf = on;
466         if (bchannel->b_state == BSTATE_ACTIVE && bchannel->b_mode == 0)
467                 ph_control(sock, on?DTMF_TONE_START:DTMF_TONE_STOP, 0, "DSP-DTMF", 1, bchannel->b_mode);
468 }
469
470
471 /*
472  * blowfish bchannel
473  */
474 void bchannel_blowfish(struct bchannel *bchannel, unsigned char *key, int len)
475 {
476         int sock;
477
478         sock = bchannel->b_sock;
479         memcpy(bchannel->b_bf_key, key, len);
480         bchannel->b_bf_len = len;
481         if (bchannel->b_state == BSTATE_ACTIVE)
482                 ph_control_block(sock, DSP_BF_ENABLE_KEY, bchannel->b_bf_key, bchannel->b_bf_len, "DSP-CRYPT", bchannel->b_bf_len, bchannel->b_mode);
483 }
484
485
486 /*
487  * pipeline bchannel
488  */
489 void bchannel_pipeline(struct bchannel *bchannel, char *pipeline)
490 {
491         int sock;
492
493         sock = bchannel->b_sock;
494         strncpy(bchannel->b_pipeline, pipeline, sizeof(bchannel->b_pipeline)-1);
495         if (bchannel->b_state == BSTATE_ACTIVE)
496                 ph_control_block(sock, DSP_PIPELINE_CFG, bchannel->b_pipeline, strlen(bchannel->b_pipeline)+1, "DSP-PIPELINE", 0, bchannel->b_mode);
497 }
498
499
500 /*
501  * gain bchannel
502  */
503 void bchannel_gain(struct bchannel *bchannel, int gain, int tx)
504 {
505         int sock;
506
507         sock = bchannel->b_sock;
508         if (tx)
509                 bchannel->b_tx_gain = gain;
510         else
511                 bchannel->b_rx_gain = gain;
512         if (bchannel->b_state == BSTATE_ACTIVE && bchannel->b_mode == 0)
513                 ph_control(sock, (tx)?DSP_VOL_CHANGE_TX:DSP_VOL_CHANGE_RX, gain, (tx)?"DSP-TX_GAIN":"DSP-RX_GAIN", gain, bchannel->b_mode);
514 }
515
516
517 /*
518  * main loop for processing messages from mISDN
519  */
520 int bchannel_handle(void)
521 {
522         int ret, work = 0;
523         struct bchannel *bchannel;
524         unsigned char buffer[2048+MISDN_HEADER_LEN];
525         struct mISDNhead *hh = (struct mISDNhead *)buffer;
526
527         /* process all bchannels */
528         bchannel = bchannel_first;
529         while(bchannel) {
530                 /* handle message from bchannel */
531                 if (bchannel->b_sock > -1) {
532                         ret = recv(bchannel->b_sock, buffer, sizeof(buffer), 0);
533                         if (ret >= (int)MISDN_HEADER_LEN) {
534                                 work = 1;
535                                 switch(hh->prim) {
536                                         /* we don't care about confirms, we use rx data to sync tx */
537                                         case PH_DATA_CNF:
538                                         break;
539
540                                         /* we receive audio data, we respond to it AND we send tones */
541                                         case PH_DATA_IND:
542                                         case PH_DATA_REQ:
543                                         case DL_DATA_IND:
544                                         case PH_CONTROL_IND:
545                                         bchannel_receive(bchannel, buffer, ret-MISDN_HEADER_LEN);
546                                         break;
547
548                                         case PH_ACTIVATE_IND:
549                                         case DL_ESTABLISH_IND:
550                                         case PH_ACTIVATE_CNF:
551                                         case DL_ESTABLISH_CNF:
552                                         CDEBUG(bchannel->call, NULL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
553                                         bchannel_activated(bchannel);
554                                         break;
555
556                                         case PH_DEACTIVATE_IND:
557                                         case DL_RELEASE_IND:
558                                         case PH_DEACTIVATE_CNF:
559                                         case DL_RELEASE_CNF:
560                                         CDEBUG(bchannel->call, NULL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
561 //                                      bchannel_deactivated(bchannel);
562                                         break;
563
564                                         default:
565                                         CERROR(bchannel->call, NULL, "child message not handled: prim(0x%x) socket(%d) data len(%d)\n", hh->prim, bchannel->b_sock, ret - MISDN_HEADER_LEN);
566                                 }
567                         } else {
568                                 if (ret < 0 && errno != EWOULDBLOCK)
569                                         CERROR(bchannel->call, NULL, "Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
570                         }
571                 }
572                 bchannel = bchannel->next;
573         }
574
575         /* if we received at least one b-frame, we will return 1 */
576         return(work);
577 }
578
579
580 /*
581  * bchannel channel handling
582  */
583 struct bchannel *bchannel_first = NULL;
584 struct bchannel *find_bchannel_handle(unsigned int handle)
585 {
586         struct bchannel *bchannel = bchannel_first;
587
588         while(bchannel) {
589                 if (bchannel->handle == handle)
590                         break;
591                 bchannel = bchannel->next;
592         }
593         return(bchannel);
594 }
595
596 #if 0
597 struct bchannel *find_bchannel_ref(unsigned int ref)
598 {
599         struct bchannel *bchannel = bchannel_first;
600
601         while(bchannel) {
602                 if (bchannel->ref == ref)
603                         break;
604                 bchannel = bchannel->next;
605         }
606         return(bchannel);
607 }
608 #endif
609
610 struct bchannel *alloc_bchannel(unsigned int handle)
611 {
612         struct bchannel **bchannelp = &bchannel_first;
613
614         while(*bchannelp)
615                 bchannelp = &((*bchannelp)->next);
616
617         *bchannelp = (struct bchannel *)calloc(1, sizeof(struct bchannel));
618         if (!*bchannelp)
619                 return(NULL);
620         (*bchannelp)->handle = handle;
621         (*bchannelp)->b_state = BSTATE_IDLE;
622         (*bchannelp)->b_sock = -1;
623                 
624         return(*bchannelp);
625 }
626
627 void free_bchannel(struct bchannel *bchannel)
628 {
629         struct bchannel **temp = &bchannel_first;
630
631         while(*temp) {
632                 if (*temp == bchannel) {
633                         *temp = (*temp)->next;
634                         if (bchannel->b_sock > -1)
635                                 bchannel_destroy(bchannel);
636                         if (bchannel->call) {
637                                 if (bchannel->call->bchannel)
638                                         bchannel->call->bchannel = NULL;
639                         }
640                         free(bchannel);
641                         return;
642                 }
643                 temp = &((*temp)->next);
644         }
645 }
646
647