• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Callbacks for the FSM
3  *
4  * Copyright (C) 1996 Universidade de Lisboa
5  *
6  * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
7  *
8  * This software may be used and distributed according to the terms of
9  * the GNU General Public License, incorporated herein by reference.
10  */
11 
12 /*
13  * Fix: 19981230 - Carlos Morgado <chbm@techie.com>
14  * Port of Nelson Escravana's <nelson.escravana@usa.net> fix to CalledPN
15  * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
16  */
17 
18 #include <linux/string.h>
19 #include <linux/kernel.h>
20 
21 #include <linux/types.h>
22 #include <linux/slab.h>
23 #include <linux/mm.h>
24 #include <linux/skbuff.h>
25 
26 #include <asm/io.h>
27 
28 #include <linux/isdnif.h>
29 
30 #include "pcbit.h"
31 #include "layer2.h"
32 #include "edss1.h"
33 #include "callbacks.h"
34 #include "capi.h"
35 
36 ushort last_ref_num = 1;
37 
38 /*
39  *  send_conn_req
40  *
41  */
42 
cb_out_1(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * cbdata)43 void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
44 	      struct callb_data *cbdata)
45 {
46 	struct sk_buff *skb;
47 	int len;
48         ushort refnum;
49 
50 
51 #ifdef DEBUG
52         printk(KERN_DEBUG "Called Party Number: %s\n",
53                cbdata->data.setup.CalledPN);
54 #endif
55         /*
56          * hdr - kmalloc in capi_conn_req
57          *     - kfree   when msg has been sent
58          */
59 
60         if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb,
61 				 chan->proto)) < 0)
62         {
63                 printk("capi_conn_req failed\n");
64                 return;
65         }
66 
67 
68         refnum = last_ref_num++ & 0x7fffU;
69 
70         chan->callref = 0;
71         chan->layer2link = 0;
72         chan->snum = 0;
73         chan->s_refnum = refnum;
74 
75         pcbit_l2_write(dev, MSG_CONN_REQ, refnum, skb, len);
76 }
77 
78 /*
79  *  rcv CONNECT
80  *  will go into ACTIVE state
81  *  send CONN_ACTIVE_RESP
82  *  send Select protocol request
83  */
84 
cb_out_2(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)85 void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
86 	      struct callb_data *data)
87 {
88         isdn_ctrl ictl;
89  	struct sk_buff *skb;
90 	int len;
91         ushort refnum;
92 
93         if ((len=capi_conn_active_resp(chan, &skb)) < 0)
94         {
95                 printk("capi_conn_active_req failed\n");
96                 return;
97         }
98 
99         refnum = last_ref_num++ & 0x7fffU;
100         chan->s_refnum = refnum;
101 
102         pcbit_l2_write(dev, MSG_CONN_ACTV_RESP, refnum, skb, len);
103 
104 
105         ictl.command = ISDN_STAT_DCONN;
106         ictl.driver=dev->id;
107         ictl.arg=chan->id;
108         dev->dev_if->statcallb(&ictl);
109 
110         /* ACTIVE D-channel */
111 
112         /* Select protocol  */
113 
114         if ((len=capi_select_proto_req(chan, &skb, 1 /*outgoing*/)) < 0) {
115                 printk("capi_select_proto_req failed\n");
116                 return;
117         }
118 
119         refnum = last_ref_num++ & 0x7fffU;
120         chan->s_refnum = refnum;
121 
122         pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len);
123 }
124 
125 
126 /*
127  * Incoming call received
128  * inform user
129  */
130 
cb_in_1(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * cbdata)131 void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
132 	     struct callb_data *cbdata)
133 {
134         isdn_ctrl ictl;
135         unsigned short refnum;
136  	struct sk_buff *skb;
137 	int len;
138 
139 
140         ictl.command = ISDN_STAT_ICALL;
141         ictl.driver=dev->id;
142         ictl.arg=chan->id;
143 
144         /*
145          *  ictl.num >= strlen() + strlen() + 5
146          */
147 
148 	if (cbdata->data.setup.CallingPN == NULL) {
149 		printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
150 		strcpy(ictl.parm.setup.phone, "0");
151 	}
152 	else {
153 		strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
154 	}
155 	if (cbdata->data.setup.CalledPN == NULL) {
156 		printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
157 		strcpy(ictl.parm.setup.eazmsn, "0");
158 	}
159 	else {
160 		strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
161 	}
162 	ictl.parm.setup.si1 = 7;
163 	ictl.parm.setup.si2 = 0;
164 	ictl.parm.setup.plan = 0;
165 	ictl.parm.setup.screen = 0;
166 
167 #ifdef DEBUG
168 	printk(KERN_DEBUG "statstr: %s\n", ictl.num);
169 #endif
170 
171         dev->dev_if->statcallb(&ictl);
172 
173 
174         if ((len=capi_conn_resp(chan, &skb)) < 0) {
175                 printk(KERN_DEBUG "capi_conn_resp failed\n");
176                 return;
177 	}
178 
179         refnum = last_ref_num++ & 0x7fffU;
180         chan->s_refnum = refnum;
181 
182         pcbit_l2_write(dev, MSG_CONN_RESP, refnum, skb, len);
183 }
184 
185 /*
186  * user has replied
187  * open the channel
188  * send CONNECT message CONNECT_ACTIVE_REQ in CAPI
189  */
190 
cb_in_2(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)191 void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
192 	     struct callb_data *data)
193 {
194         unsigned short refnum;
195 	struct sk_buff *skb;
196         int len;
197 
198         if ((len = capi_conn_active_req(chan, &skb)) < 0) {
199                 printk(KERN_DEBUG "capi_conn_active_req failed\n");
200                 return;
201         }
202 
203 
204         refnum = last_ref_num++ & 0x7fffU;
205         chan->s_refnum = refnum;
206 
207 	printk(KERN_DEBUG "sending MSG_CONN_ACTV_REQ\n");
208         pcbit_l2_write(dev, MSG_CONN_ACTV_REQ, refnum, skb, len);
209 }
210 
211 /*
212  * CONN_ACK arrived
213  * start b-proto selection
214  *
215  */
216 
cb_in_3(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)217 void cb_in_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
218 	     struct callb_data *data)
219 {
220         unsigned short refnum;
221  	struct sk_buff *skb;
222 	int len;
223 
224         if ((len = capi_select_proto_req(chan, &skb, 0 /*incoming*/)) < 0)
225         {
226                 printk("capi_select_proto_req failed\n");
227                 return;
228         }
229 
230         refnum = last_ref_num++ & 0x7fffU;
231         chan->s_refnum = refnum;
232 
233         pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len);
234 
235 }
236 
237 
238 /*
239  * Received disconnect ind on active state
240  * send disconnect resp
241  * send msg to user
242  */
cb_disc_1(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)243 void cb_disc_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
244 	       struct callb_data *data)
245 {
246  	struct sk_buff *skb;
247 	int len;
248         ushort refnum;
249         isdn_ctrl ictl;
250 
251         if ((len = capi_disc_resp(chan, &skb)) < 0) {
252                 printk("capi_disc_resp failed\n");
253                 return;
254         }
255 
256         refnum = last_ref_num++ & 0x7fffU;
257         chan->s_refnum = refnum;
258 
259         pcbit_l2_write(dev, MSG_DISC_RESP, refnum, skb, len);
260 
261         ictl.command = ISDN_STAT_BHUP;
262         ictl.driver=dev->id;
263         ictl.arg=chan->id;
264         dev->dev_if->statcallb(&ictl);
265 }
266 
267 
268 /*
269  *  User HANGUP on active/call proceeding state
270  *  send disc.req
271  */
cb_disc_2(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)272 void cb_disc_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
273 	       struct callb_data *data)
274 {
275  	struct sk_buff *skb;
276 	int len;
277         ushort refnum;
278 
279         if ((len = capi_disc_req(chan->callref, &skb, CAUSE_NORMAL)) < 0)
280         {
281                 printk("capi_disc_req failed\n");
282                 return;
283         }
284 
285         refnum = last_ref_num++ & 0x7fffU;
286         chan->s_refnum = refnum;
287 
288         pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb, len);
289 }
290 
291 /*
292  *  Disc confirm received send BHUP
293  *  Problem: when the HL driver sends the disc req itself
294  *           LL receives BHUP
295  */
cb_disc_3(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)296 void cb_disc_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
297 	       struct callb_data *data)
298 {
299         isdn_ctrl ictl;
300 
301         ictl.command = ISDN_STAT_BHUP;
302         ictl.driver=dev->id;
303         ictl.arg=chan->id;
304         dev->dev_if->statcallb(&ictl);
305 }
306 
cb_notdone(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)307 void cb_notdone(struct pcbit_dev * dev, struct pcbit_chan* chan,
308 		struct callb_data *data)
309 {
310 }
311 
312 /*
313  * send activate b-chan protocol
314  */
cb_selp_1(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)315 void cb_selp_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
316 	       struct callb_data *data)
317 {
318  	struct sk_buff *skb;
319 	int len;
320         ushort refnum;
321 
322         if ((len = capi_activate_transp_req(chan, &skb)) < 0)
323         {
324                 printk("capi_conn_activate_transp_req failed\n");
325                 return;
326         }
327 
328         refnum = last_ref_num++ & 0x7fffU;
329         chan->s_refnum = refnum;
330 
331         pcbit_l2_write(dev, MSG_ACT_TRANSP_REQ, refnum, skb, len);
332 }
333 
334 /*
335  *  Inform User that the B-channel is available
336  */
cb_open(struct pcbit_dev * dev,struct pcbit_chan * chan,struct callb_data * data)337 void cb_open(struct pcbit_dev * dev, struct pcbit_chan* chan,
338 	     struct callb_data *data)
339 {
340         isdn_ctrl ictl;
341 
342         ictl.command = ISDN_STAT_BCONN;
343         ictl.driver=dev->id;
344         ictl.arg=chan->id;
345         dev->dev_if->statcallb(&ictl);
346 }
347 
348 
349 
350