56d9e0d76c890b5cf613770ebef158541395c885
[lcr.git] / channel.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN bchannel access (for Asterisk)                                      **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "main.h"
17 #include <unistd.h>
18 #include <poll.h>
19 #include <errno.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 extern "C" {
25 #include <net_l2.h>
26 }
27
28 #if 0
29 #ifndef ISDN_PID_L2_B_USER
30 #define ISDN_PID_L2_B_USER 0x420000ff
31 #endif
32 #ifndef ISDN_PID_L3_B_USER
33 #define ISDN_PID_L3_B_USER 0x430000ff
34 #endif
35 #endif
36 #ifndef ISDN_PID_L4_B_USER
37 #define ISDN_PID_L4_B_USER 0x440000ff
38 #endif
39
40 /* used for udevice */
41 int entity = 0;
42
43 /* the device handler and port list */
44 int mISDNdevice = -1;
45
46
47 /* open mISDN device */
48 void mISDNdevice_open(void)
49 {
50         /* open mISDNdevice if not already open */
51         if (mISDNdevice < 0)
52         {
53                 ret = mISDN_open();
54                 if (ret < 0)
55                 {
56                         PERROR("cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
57                         return(NULL);
58                 }
59                 mISDNdevice = ret;
60                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
61         }
62 }
63
64 /* close mISDN device */
65 void mISDNdevice_close(void)
66 {
67         if (mISDNdevice > -1)
68         {
69                 mISDN_close();
70                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
71         }
72 }
73
74 /* create bchannel layer */
75 unsigned long mISDN_createlayer(unsigned long stid)
76 {
77         unsigned long addr;
78
79         /* create new layer */
80         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel stid=0%x.\n" , stid);
81         memset(&li, 0, sizeof(li));
82         memset(&pid, 0, sizeof(pid));
83         li.object_id = -1;
84         li.extentions = 0;
85         li.st = stid;
86         UCPY(li.name, "B L4");
87         li.pid.layermask = ISDN_LAYER((4));
88         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
89         ret = mISDN_new_layer(mISDNdevice, &li);
90         if (ret)
91         {
92                 failed_new_layer:
93                 PERROR("mISDN_new_layer() failed to add bchannel stid=0%x.\n", stid);
94                 goto failed;
95         }
96         addr = li.id;
97         if (!li.id)
98         {
99                 goto failed_new_layer;
100         }
101         PDEBUG(DEBUG_BCHANNEL, "new layer (addr=0x%x)\n", addr);
102
103         /* create new stack */
104         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
105         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
106         pid.protocol[3] = ISDN_PID_L3_B_DSP;
107         pid.protocol[4] = ISDN_PID_L4_B_USER;
108         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
109         ret = mISDN_set_stack(mISDNdevice, stid, &pid);
110         if (ret)
111         {
112                 stack_error:
113                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%x\n", ret, stid);
114                 mISDN_write_frame(mISDNdevice, buff, addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
115                 goto failed;
116         }
117         ret = mISDN_get_setstack_ind(mISDNdevice, addr);
118         if (ret)
119                 goto stack_error;
120
121         /* get layer id */
122         addr = mISDN_get_layerid(mISDNdevice, stid, 4);
123         if (!addr)
124                 goto stack_error;
125 }
126
127 /* destroy bchannel layer */
128 void mISDN_destroylayer(unsigned long stid, unsigned long addr)
129 {
130         /* remove our stack only if set */
131         if (addr)
132         {
133                 PDEBUG(DEBUG_BCHANNEL, "free stack (addr=0x%x)\n", addr);
134                 mISDN_clear_stack(mISDNdevice, stid);
135                 mISDN_write_frame(mISDNdevice, buff, addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
136         }
137 }
138
139 /* do activation and deactivation of bchannel */
140 static void mISDN_bchannelactivate(unsigned long addr, int activate)
141 {
142         iframe_t act;
143
144         /* activate bchannel */
145         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
146         act.addr = addr | FLG_MSG_DOWN;
147         act.dinfo = 0;
148         act.len = 0;
149         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
150 }
151
152 /* handle all mISDN messages */
153 int mISDN_handler(void)
154 {
155         int ret;
156         msg_t *msg;
157         iframe_t *frm;
158         struct mISDNport *mISDNport;
159         class PmISDN *isdnport;
160         net_stack_t *nst;
161         msg_t *dmsg;
162         mISDNuser_head_t *hh;
163         int i;
164
165         /* no device, no read */
166         if (mISDNdevice < 0)
167                 return(0);
168
169         /* get message from kernel */
170         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
171                 return(1);
172         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
173         if (ret < 0)
174         {
175                 free_msg(msg);
176                 if (errno == EAGAIN)
177                         return(0);
178                 FATAL("Failed to do mISDN_read()\n");
179         }
180         if (!ret)
181         {
182                 free_msg(msg);
183 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
184                 return(0);
185         }
186         msg->len = ret;
187         frm = (iframe_t *)msg->data;
188
189         /* global prim */
190         switch(frm->prim)
191         {
192                 case MGR_DELLAYER | CONFIRM:
193                 case MGR_INITTIMER | CONFIRM:
194                 case MGR_ADDTIMER | CONFIRM:
195                 case MGR_DELTIMER | CONFIRM:
196                 case MGR_REMOVETIMER | CONFIRM:
197                 free_msg(msg);
198                 return(1);
199         }
200
201         /* look for channel instance, that has the address of this message */
202         chan = chan_first;
203         while(chan)
204         {
205                 if (frm->addr == chan->b_addr)
206                         break;
207                 chan = chan->next;
208         } 
209         if (!chan)
210         {
211                 PERROR("message belongs to no chan: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
212                 goto out;
213         }
214
215         /* b-message */
216         switch(frm->prim)
217         {
218                 /* we don't care about confirms, we use rx data to sync tx */
219                 case PH_DATA | CONFIRM:
220                 case DL_DATA | CONFIRM:
221                 break;
222
223                 /* we receive audio data, we respond to it AND we send tones */
224                 case PH_DATA | INDICATION:
225                 case DL_DATA | INDICATION:
226                 case PH_CONTROL | INDICATION:
227                 i = 0;
228                 chan->bchannel_receive(frm);
229                 break;
230
231                 case PH_ACTIVATE | INDICATION:
232                 case DL_ESTABLISH | INDICATION:
233                 case PH_ACTIVATE | CONFIRM:
234                 case DL_ESTABLISH | CONFIRM:
235                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
236                 chan->b_active = 1;
237                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
238                 break;
239
240                 case PH_DEACTIVATE | INDICATION:
241                 case DL_RELEASE | INDICATION:
242                 case PH_DEACTIVATE | CONFIRM:
243                 case DL_RELEASE | CONFIRM:
244                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
245                 chan->b_active = 0;
246                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
247                 break;
248
249                 default:
250                 PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
251         }
252
253         out:
254         free_msg(msg);
255         return(1);
256 }
257