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