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