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 36ushort last_ref_num = 1; 37 38/* 39 * send_conn_req 40 * 41 */ 42 43void 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 85void 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 131void 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 191void 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 217void 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 */ 243void 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 */ 272void 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 */ 296void 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 307void 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 */ 315void 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 */ 337void 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