]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/capi/capi_msgs.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / i4b / capi / capi_msgs.c
1 /*-
2  * Copyright (c) 2001 Cubical Solutions Ltd. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25
26 /* capi/capi_msgs.c     The CAPI i4b message handlers.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/systm.h>
35 #include <sys/mbuf.h>
36 #include <sys/socket.h>
37 #include <net/if.h>
38
39 #include <i4b/include/i4b_debug.h>
40 #include <i4b/include/i4b_ioctl.h>
41 #include <i4b/include/i4b_cause.h>
42
43 #include <i4b/include/i4b_l3l4.h>
44 #include <i4b/include/i4b_mbuf.h>
45 #include <i4b/include/i4b_global.h>
46
47 #include <i4b/layer4/i4b_l4.h>
48
49 #include <i4b/capi/capi.h>
50 #include <i4b/capi/capi_msgs.h>
51
52 /*
53 //  Administrative messages:
54 //  ------------------------
55 */
56
57 void capi_listen_req(capi_softc_t *sc, u_int32_t CIP)
58 {
59     struct mbuf *m = i4b_Dgetmbuf(8 + 18);
60     u_int8_t *msg;
61     u_int16_t msgid;
62
63     if (!m) {
64         printf("capi%d: can't get mbuf for listen_req\n", sc->sc_unit);
65         return;
66     }
67
68     msgid = sc->sc_msgid++;
69
70     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
71     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
72     msg = capimsg_setu16(msg, CAPI_LISTEN_REQ);
73     msg = capimsg_setu16(msg, msgid);
74
75     msg = capimsg_setu32(msg, 1); /* Controller */
76     msg = capimsg_setu32(msg, 0); /* Info mask */
77     msg = capimsg_setu32(msg, CIP);
78     msg = capimsg_setu32(msg, 0);
79     msg = capimsg_setu8(msg, 0);
80     msg = capimsg_setu8(msg, 0);
81
82     sc->send(sc, m);
83 }
84
85 void capi_listen_conf(capi_softc_t *sc, struct mbuf *m_in)
86 {
87     u_int8_t *msg = mtod(m_in, u_int8_t*);
88     u_int16_t Info;
89
90     capimsg_getu16(msg + 12, &Info);
91
92     if (Info == 0) {
93         /* We are now listening. */
94
95         sc->sc_state = C_UP;
96         ctrl_desc[sc->ctrl_unit].dl_est = DL_UP;
97
98         i4b_l4_l12stat(sc->ctrl_unit, 1, 1);
99         i4b_l4_l12stat(sc->ctrl_unit, 2, 1);
100
101     } else {
102         /* XXX sc->sc_state = C_DOWN ? XXX */
103         printf("capi%d: can't listen, info=%04x\n", sc->sc_unit, Info);
104     }
105 }
106
107 void capi_info_ind(capi_softc_t *sc, struct mbuf *m_in)
108 {
109     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
110     u_int8_t *msg = mtod(m_in, u_int8_t*);
111     u_int16_t applid, msgid;
112     u_int32_t PLCI;
113
114     if (!m) {
115         printf("capi%d: can't get mbuf for info_resp\n", sc->sc_unit);
116         return;
117     }
118
119     msg = capimsg_getu16(msg + 2, &applid);
120     msg = capimsg_getu16(msg + 2, &msgid);
121     msg = capimsg_getu32(msg, &PLCI);
122
123     /* i4b_l4_info_ind() */
124     
125     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
126     msg = capimsg_setu16(msg, applid);
127     msg = capimsg_setu16(msg, CAPI_INFO_RESP);
128     msg = capimsg_setu16(msg, msgid);
129
130     msg = capimsg_setu32(msg, PLCI);
131
132     sc->send(sc, m);
133 }
134
135 void capi_alert_req(capi_softc_t *sc, call_desc_t *cd)
136 {
137     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
138     u_int8_t *msg;
139     u_int16_t msgid;
140     u_int32_t PLCI;
141
142     if (!m) {
143         printf("capi%d: can't get mbuf for alert_req\n", sc->sc_unit);
144         return;
145     }
146
147     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
148     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
149
150     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
151     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
152     msg = capimsg_setu16(msg, CAPI_ALERT_REQ);
153     msg = capimsg_setu16(msg, msgid);
154
155     msg = capimsg_setu32(msg, PLCI);
156     msg = capimsg_setu8(msg, 0);
157
158     sc->send(sc, m);
159 }
160
161 void capi_alert_conf(capi_softc_t *sc, struct mbuf *m_in)
162 {
163     u_int8_t *msg = mtod(m_in, u_int8_t*);
164     u_int16_t Info;
165
166     msg = capimsg_getu16(msg + 12, &Info);
167
168     if (Info) {
169         printf("capi%d: can't alert, info=%04x\n", sc->sc_unit, Info);
170     }
171 }
172
173 /*
174 //  Outgoing call setup:
175 //  --------------------
176 //
177 //             CAPI_CONNECT_REQ -->
178 //                              <-- CAPI_CONNECT_CONF
179 //                       (notify Layer 4)
180 //                              <-- CAPI_CONNECT_ACTIVE_IND
181 //     CAPI_CONNECT_ACTIVE_RESP -->
182 //          CAPI_CONNECT_B3_REQ -->
183 //                              <-- CAPI_CONNECT_B3_CONF
184 //                              <-- CAPI_CONNECT_B3_ACTIVE_IND
185 //  CAPI_CONNECT_B3_ACTIVE_RESP -->
186 //                       (notify Layer 4)
187 */
188
189 void capi_connect_req(capi_softc_t *sc, call_desc_t *cd)
190 {
191     struct mbuf *m;
192     u_int8_t *msg;
193     u_int16_t msgid;
194     int slen = strlen(cd->src_telno);
195     int dlen = strlen(cd->dst_telno);
196
197     m = i4b_Dgetmbuf(8 + 27 + slen + dlen);
198     if (!m) {
199         printf("capi%d: can't get mbuf for connect_req\n", sc->sc_unit);
200         return;
201     }
202
203     cd->crflag = CRF_ORIG;
204
205     sc->sc_bchan[cd->channelid].cdid = cd->cdid;
206     sc->sc_bchan[cd->channelid].bprot = cd->bprot;
207     sc->sc_bchan[cd->channelid].state = B_CONNECT_CONF;
208     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
209     ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
210
211     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
212     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
213     msg = capimsg_setu16(msg, CAPI_CONNECT_REQ);
214     msg = capimsg_setu16(msg, msgid);
215
216     msg = capimsg_setu32(msg, 1); /* Controller */
217
218     switch (cd->bprot) {
219     case BPROT_NONE:
220         msg = capimsg_setu16(msg, 0x0010); /* Telephony */
221         break;
222
223     case BPROT_RHDLC:
224         msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
225         break;
226
227     default:
228         msg = capimsg_setu16(msg, 0x0002); /* Unrestricted digital */
229     }
230
231     msg = capimsg_setu8(msg, 1 + dlen);
232     msg = capimsg_setu8(msg, 0x80);
233     strncpy(msg, cd->dst_telno, dlen);
234
235     msg = capimsg_setu8(msg + dlen, 2 + slen);
236     msg = capimsg_setu8(msg, 0x00);
237     msg = capimsg_setu8(msg, 0x80); /* Presentation and screening indicator */
238     strncpy(msg, cd->src_telno, slen);
239
240     msg = capimsg_setu8(msg + slen, 0); /* Called & */
241     msg = capimsg_setu8(msg, 0); /* Calling party subaddress */
242     
243     msg = capimsg_setu8(msg, 15); /* B protocol */
244     if (cd->bprot == BPROT_NONE)
245         msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
246     else
247         msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
248     msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
249     msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
250     msg = capimsg_setu8(msg, 0); /* B1 parameters */
251     msg = capimsg_setu8(msg, 0); /* B2 parameters */
252     msg = capimsg_setu8(msg, 0); /* B3 parameters */
253
254     msg = capimsg_setu8(msg, 0); /* Bearer Capability */
255     msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
256     msg = capimsg_setu8(msg, 0); /* High Layer Compatibility */
257     msg = capimsg_setu8(msg, 0); /* Additional Info */
258
259     sc->send(sc, m);
260 }
261
262 void capi_connect_conf(capi_softc_t *sc, struct mbuf *m_in)
263 {
264     u_int8_t *msg = mtod(m_in, u_int8_t*);
265     call_desc_t *cd;
266     u_int16_t msgid;
267     u_int32_t PLCI;
268     u_int16_t Info;
269     int bch;
270
271     msg = capimsg_getu16(msg + 6, &msgid);
272     msg = capimsg_getu32(msg, &PLCI);
273     msg = capimsg_getu16(msg, &Info);
274
275     for (bch = 0; bch < sc->sc_nbch; bch++)
276         if ((sc->sc_bchan[bch].state == B_CONNECT_CONF) &&
277             (sc->sc_bchan[bch].msgid == msgid))
278             break;
279
280     if ((bch == sc->sc_nbch) ||
281         (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
282         printf("capi%d: can't find channel for connect_conf PLCI %x\n",
283                sc->sc_unit, PLCI);
284         return;
285     }
286
287     if (Info == 0) {
288         sc->sc_bchan[bch].state = B_CONNECT_ACTIVE_IND;
289         sc->sc_bchan[bch].ncci = PLCI;
290
291         i4b_l4_proceeding_ind(cd);
292
293     } else {
294         SET_CAUSE_TV(cd->cause_out, CAUSET_I4B, CAUSE_I4B_L1ERROR);
295         i4b_l4_disconnect_ind(cd);
296         freecd_by_cd(cd);
297
298         sc->sc_bchan[bch].state = B_FREE;
299         ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
300
301         printf("capi%d: can't connect out, info=%04x\n", sc->sc_unit, Info);
302     }
303 }
304
305 void capi_connect_active_ind(capi_softc_t *sc, struct mbuf *m_in)
306 {
307     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
308     u_int8_t *msg = mtod(m_in, u_int8_t*);
309     call_desc_t *cd;
310     u_int16_t applid, msgid;
311     u_int32_t PLCI;
312     int bch;
313
314     if (!m) {
315         printf("capi%d: can't get mbuf for active_ind\n", sc->sc_unit);
316         return;
317     }
318
319     msg = capimsg_getu16(msg + 2, &applid);
320     msg = capimsg_getu16(msg + 2, &msgid);
321     msg = capimsg_getu32(msg, &PLCI);
322
323     for (bch = 0; bch < sc->sc_nbch; bch++)
324         if ((sc->sc_bchan[bch].state == B_CONNECT_ACTIVE_IND) &&
325             (sc->sc_bchan[bch].ncci == PLCI))
326             break;
327
328     if ((bch == sc->sc_nbch) ||
329         (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
330         printf("capi%d: can't find channel for active_resp, PLCI %x\n",
331                sc->sc_unit, PLCI);
332         return;
333     }
334
335     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
336     msg = capimsg_setu16(msg, applid);
337     msg = capimsg_setu16(msg, CAPI_CONNECT_ACTIVE_RESP);
338     msg = capimsg_setu16(msg, msgid);
339
340     msg = capimsg_setu32(msg, PLCI);
341
342     sc->send(sc, m);
343
344     if (cd->crflag == CRF_ORIG) {
345         capi_connect_b3_req(sc, cd);
346
347     } else {
348         sc->sc_bchan[bch].state = B_CONNECT_B3_IND;
349     }
350 }
351
352 void capi_connect_b3_req(capi_softc_t *sc, call_desc_t *cd)
353 {
354     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
355     u_int8_t *msg;
356     u_int16_t msgid;
357     u_int32_t PLCI;
358
359     if (!m) {
360         printf("capi%d: can't get mbuf for connect_b3_req\n", sc->sc_unit);
361         return;
362     }
363
364     sc->sc_bchan[cd->channelid].state = B_CONNECT_B3_CONF;
365     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
366     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
367
368     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
369     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
370     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_REQ);
371     msg = capimsg_setu16(msg, msgid);
372
373     msg = capimsg_setu32(msg, PLCI);
374     msg = capimsg_setu8(msg, 0); /* NCPI */
375
376     sc->send(sc, m);
377 }
378
379 void capi_connect_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
380 {
381     u_int8_t *msg = mtod(m_in, u_int8_t*);
382     call_desc_t *cd;
383     u_int16_t msgid;
384     u_int32_t NCCI;
385     u_int16_t Info;
386     int bch;
387
388     msg = capimsg_getu16(msg + 6, &msgid);
389     msg = capimsg_getu32(msg, &NCCI);
390     msg = capimsg_getu16(msg, &Info);
391
392     for (bch = 0; bch < sc->sc_nbch; bch++)
393         if ((sc->sc_bchan[bch].state == B_CONNECT_B3_CONF) &&
394             (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
395             break;
396
397     if ((bch == sc->sc_nbch) ||
398         (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
399         printf("capi%d: can't find channel for connect_b3_conf NCCI %x\n",
400                sc->sc_unit, NCCI);
401         return;
402     }
403
404     if (Info == 0) {
405         sc->sc_bchan[bch].ncci = NCCI;
406         sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
407
408     } else {
409         SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_OOO); /* XXX */
410         i4b_l4_disconnect_ind(cd);
411         freecd_by_cd(cd);
412
413         ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_RSVD;
414
415         printf("capi%d: can't connect_b3 out, info=%04x\n", sc->sc_unit, Info);
416
417         capi_disconnect_req(sc, cd);
418     }
419 }
420
421 void capi_connect_b3_active_ind(capi_softc_t *sc, struct mbuf *m_in)
422 {
423     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
424     u_int8_t *msg = mtod(m_in, u_int8_t*);
425     call_desc_t *cd;
426     u_int16_t applid, msgid;
427     u_int32_t NCCI;
428     int bch;
429
430     if (!m) {
431         printf("capi%d: can't get mbuf for b3_active_ind\n", sc->sc_unit);
432         return;
433     }
434
435     msg = capimsg_getu16(msg + 2, &applid);
436     msg = capimsg_getu16(msg + 2, &msgid);
437     msg = capimsg_getu32(msg, &NCCI);
438
439     for (bch = 0; bch < sc->sc_nbch; bch++)
440         if ((sc->sc_bchan[bch].state == B_CONNECT_B3_ACTIVE_IND) &&
441             (sc->sc_bchan[bch].ncci == NCCI))
442             break;
443
444     if ((bch == sc->sc_nbch) ||
445         (cd = cd_by_cdid(sc->sc_bchan[bch].cdid)) == NULL) {
446         printf("capi%d: can't find channel for b3_active_resp NCCI %x\n",
447                sc->sc_unit, NCCI);
448         return;
449     }
450
451     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
452     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
453     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_ACTIVE_RESP);
454     msg = capimsg_setu16(msg, msgid);
455
456     msg = capimsg_setu32(msg, NCCI);
457
458     sc->send(sc, m);
459
460     sc->sc_bchan[bch].state = B_CONNECTED;
461     i4b_l4_connect_active_ind(cd);
462 }
463
464 /*
465 //  Incoming call setup:
466 //  --------------------
467 //
468 //                              <-- CAPI_CONNECT_IND
469 //                       (consult Layer 4)
470 //            CAPI_CONNECT_RESP -->
471 //                              <-- CAPI_CONNECT_ACTIVE_IND
472 //     CAPI_CONNECT_ACTIVE_RESP -->
473 //                              <-- CAPI_CONNECT_B3_IND
474 //         CAPI_CONNECT_B3_RESP -->
475 //                              <-- CAPI_CONNECT_B3_ACTIVE_IND
476 //  CAPI_CONNECT_B3_ACTIVE_RESP -->
477 //                       (notify Layer 4)
478 */
479
480 void capi_connect_ind(capi_softc_t *sc, struct mbuf *m_in)
481 {
482     u_int8_t *msg = mtod(m_in, u_int8_t*);
483     call_desc_t *cd;
484     u_int16_t applid, msgid;
485     u_int32_t PLCI;
486     u_int16_t CIP;
487     u_int8_t x, y, z;
488     int bch;
489
490     if ((cd = reserve_cd()) == NULL) {
491         printf("capi%d: can't get cd for connect_ind\n", sc->sc_unit);
492         return;
493     }
494
495     cd->controller = sc->ctrl_unit;
496     cd->channelexcl = FALSE;
497
498     for (bch = 0; bch < sc->sc_nbch; bch++)
499         if (sc->sc_bchan[bch].state == B_FREE) break;
500     sc->sc_bchan[bch].state = B_CONNECT_IND;
501     cd->channelid = bch; /* XXX CHAN_ANY XXX */
502
503     cd->crflag = CRF_DEST;
504     cd->cr = get_rand_cr(sc->sc_unit);
505     cd->scr_ind = SCR_NONE;
506     cd->prs_ind = PRS_NONE;
507     cd->bprot = BPROT_NONE;
508     cd->ilt = NULL;
509     cd->dlt = NULL;
510     cd->display[0] = '\0';
511     cd->datetime[0] = '\0';
512
513     msg = capimsg_getu16(msg + 2, &applid);
514     msg = capimsg_getu16(msg + 2, &msgid);
515     msg = capimsg_getu32(msg, &PLCI);
516     msg = capimsg_getu16(msg, &CIP);
517
518     cd->event = (int) msgid; /* XXX overload */
519     cd->Q931state = (int) PLCI; /* XXX overload */
520
521     switch (CIP) {
522     case 0x0010:
523     case 0x0001: cd->bprot = BPROT_NONE; break;
524     case 0x0002: cd->bprot = BPROT_RHDLC; break;
525     default:
526         NDBGL4(L4_CAPIDBG, "capi%d: unknown CIP = %d", sc->sc_unit, CIP);
527         cd->bprot = BPROT_NONE;
528     }
529
530     msg = capimsg_getu8(msg, &x); /* Called party struct len */
531     if (x) {
532         msg = capimsg_getu8(msg, &y); /* Numbering plan */
533         z = x - 1;
534         if (z >= TELNO_MAX) z = (TELNO_MAX-1);
535         strncpy(cd->dst_telno, msg, z);
536         msg += x;
537         x = z;
538     }
539     cd->dst_telno[x] = '\0';
540
541     msg = capimsg_getu8(msg, &x); /* Calling party struct len */
542     if (x) {
543         msg = capimsg_getu8(msg, &y); /* Numbering plan */
544         msg = capimsg_getu8(msg, &y); /* Screening/Presentation */
545         if ((y & 0x80) == 0) { /* screening used */
546             cd->scr_ind = (y & 3) + SCR_USR_NOSC;
547             cd->prs_ind = ((y >> 5) & 3) + PRS_ALLOWED;
548         }
549         z = x - 2;
550         if (z >= TELNO_MAX) z = (TELNO_MAX-1);
551         strncpy(cd->src_telno, msg, z);
552         msg += x;
553         x = z;
554     }
555     cd->src_telno[x] = '\0';
556
557     i4b_l4_connect_ind(cd);
558 }
559
560 void capi_connect_resp(capi_softc_t *sc, call_desc_t *cd)
561 {
562     struct mbuf *m;
563     u_int8_t *msg;
564     u_int16_t msgid;
565     u_int32_t PLCI;
566     int dlen = strlen(cd->dst_telno);
567
568     m = i4b_Dgetmbuf(8 + 21 + dlen);
569     if (!m) {
570         printf("capi%d: can't get mbuf for connect_resp\n", sc->sc_unit);
571         return;
572     }
573
574     msgid = (u_int16_t) cd->event;
575     PLCI = (u_int32_t) cd->Q931state;
576
577     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
578     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
579     msg = capimsg_setu16(msg, CAPI_CONNECT_RESP);
580     msg = capimsg_setu16(msg, msgid);
581
582     msg = capimsg_setu32(msg, PLCI);
583
584     switch (cd->response) {
585     case SETUP_RESP_ACCEPT:
586         sc->sc_bchan[cd->channelid].cdid = cd->cdid;
587         sc->sc_bchan[cd->channelid].ncci = PLCI;
588         sc->sc_bchan[cd->channelid].state = B_CONNECT_ACTIVE_IND;
589         ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_USED;
590         msg = capimsg_setu16(msg, 0); /* Accept the call */
591         break;
592
593     case SETUP_RESP_REJECT:
594         sc->sc_bchan[cd->channelid].state = B_FREE;
595         ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
596         msg = capimsg_setu16(msg, 2); /* Reject, normal call clearing */
597         break;
598
599     case SETUP_RESP_DNTCRE:
600         sc->sc_bchan[cd->channelid].state = B_FREE;
601         ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
602         if (sc->sc_nbch == 30) {
603             /* With PRI, we can't really ignore calls  -- normal clearing */
604             msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_NCCLR));
605         } else {
606             msg = capimsg_setu16(msg, 1); /* Ignore */
607         }
608         break;
609
610     default:
611         sc->sc_bchan[cd->channelid].state = B_FREE;
612         ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_FREE;
613         msg = capimsg_setu16(msg, (0x3480|CAUSE_Q850_CALLREJ));
614     }
615
616     msg = capimsg_setu8(msg, 15); /* B protocol */
617     if (cd->bprot == BPROT_NONE)
618         msg = capimsg_setu16(msg, 1); /* B1 protocol = transparent */
619     else
620         msg = capimsg_setu16(msg, 0); /* B1 protocol = HDLC */
621     msg = capimsg_setu16(msg, 1); /* B2 protocol = transparent */
622     msg = capimsg_setu16(msg, 0); /* B3 protocol = transparent */
623     msg = capimsg_setu8(msg, 0); /* B1 parameters */
624     msg = capimsg_setu8(msg, 0); /* B2 parameters */
625     msg = capimsg_setu8(msg, 0); /* B3 parameters */
626
627     msg = capimsg_setu8(msg, 1 + dlen);
628     msg = capimsg_setu8(msg, 0x80); /* Numbering plan */
629     strncpy(msg, cd->dst_telno, dlen);
630     msg = capimsg_setu8(msg + dlen, 0); /* Connected subaddress */
631     msg = capimsg_setu8(msg, 0); /* Low Layer Compatibility */
632     msg = capimsg_setu8(msg, 0); /* Additional Info */
633
634     sc->send(sc, m);
635 }
636
637 void capi_connect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
638 {
639     struct mbuf *m = i4b_Dgetmbuf(8 + 7);
640     u_int8_t *msg = mtod(m_in, u_int8_t*);
641     u_int16_t applid, msgid;
642     u_int32_t NCCI;
643     int bch;
644
645     if (!m) {
646         printf("capi%d: can't get mbuf for connect_b3_resp\n", sc->sc_unit);
647         return;
648     }
649
650     msg = capimsg_getu16(msg + 2, &applid);
651     msg = capimsg_getu16(msg + 2, &msgid);
652     msg = capimsg_getu32(msg, &NCCI);
653
654     for (bch = 0; bch < sc->sc_nbch; bch++)
655         if ((sc->sc_bchan[bch].state == B_CONNECT_B3_IND) &&
656             (sc->sc_bchan[bch].ncci == (NCCI & CAPI_PLCI_MASK)))
657             break;
658
659     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
660     msg = capimsg_setu16(msg, applid);
661     msg = capimsg_setu16(msg, CAPI_CONNECT_B3_RESP);
662     msg = capimsg_setu16(msg, msgid);
663
664     msg = capimsg_setu32(msg, NCCI);
665
666     if (bch == sc->sc_nbch) {
667         printf("capi%d: can't get cd for connect_b3_resp NCCI %x\n",
668                sc->sc_unit, NCCI);
669         msg = capimsg_setu16(msg, 8); /* Reject, destination OOO */
670
671     } else {
672         sc->sc_bchan[bch].ncci = NCCI;
673         sc->sc_bchan[bch].state = B_CONNECT_B3_ACTIVE_IND;
674         msg = capimsg_setu16(msg, 0); /* Accept */
675     }
676
677     msg = capimsg_setu8(msg, 0); /* NCPI */
678
679     sc->send(sc, m);
680 }
681
682 /*
683 //  Data transfer:
684 //  --------------
685 */
686
687 void capi_data_b3_req(capi_softc_t *sc, int chan, struct mbuf *m_b3)
688 {
689     struct mbuf *m = i4b_Dgetmbuf(8 + 14);
690     u_int8_t *msg;
691     u_int16_t msgid;
692
693     if (!m) {
694         printf("capi%d: can't get mbuf for data_b3_req\n", sc->sc_unit);
695         return;
696     }
697
698     msgid = sc->sc_bchan[chan].msgid = sc->sc_msgid++;
699     sc->sc_bchan[chan].busy = 1;
700
701     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
702     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
703     msg = capimsg_setu16(msg, CAPI_DATA_B3_REQ);
704     msg = capimsg_setu16(msg, msgid);
705
706     msg = capimsg_setu32(msg, sc->sc_bchan[chan].ncci);
707     msg = capimsg_setu32(msg, (u_int32_t) m_b3->m_data); /* Pointer */
708     msg = capimsg_setu16(msg, m_b3->m_len);
709     msg = capimsg_setu16(msg, chan);
710     msg = capimsg_setu16(msg, 0); /* Flags */
711
712     m->m_next = m_b3;
713
714     sc->send(sc, m);
715 }
716
717 void capi_data_b3_conf(capi_softc_t *sc, struct mbuf *m_in)
718 {
719     u_int8_t *msg = mtod(m_in, u_int8_t*);
720     u_int32_t NCCI;
721     u_int16_t handle;
722     u_int16_t Info;
723
724     msg = capimsg_getu32(msg + 8, &NCCI);
725     msg = capimsg_getu16(msg, &handle);
726     msg = capimsg_getu16(msg, &Info);
727
728     if (Info == 0) {
729         sc->sc_bchan[handle].busy = 0;
730         capi_start_tx(sc, handle);
731
732     } else {
733         printf("capi%d: data_b3_conf NCCI %x handle %x info=%04x\n",
734                sc->sc_unit, NCCI, handle, Info);
735     }
736 }
737
738 void capi_data_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
739 {
740     struct mbuf *m = i4b_Dgetmbuf(8 + 6);
741     u_int8_t *msg = mtod(m_in, u_int8_t*);
742     u_int16_t applid, msgid;
743     u_int32_t NCCI;
744     u_int16_t handle;
745     int bch;
746
747     if (!m) {
748         printf("capi%d: can't get mbuf for data_b3_resp\n", sc->sc_unit);
749         return;
750     }
751
752     msg = capimsg_getu16(msg + 2, &applid);
753     msg = capimsg_getu16(msg + 2, &msgid);
754     msg = capimsg_getu32(msg, &NCCI);
755     msg = capimsg_getu16(msg + 6, &handle);
756
757     for (bch = 0; bch < sc->sc_nbch; bch++)
758         if ((sc->sc_bchan[bch].state == B_CONNECTED) &&
759             (sc->sc_bchan[bch].ncci == NCCI))
760             break;
761
762     if (bch == sc->sc_nbch) {
763         printf("capi%d: can't find channel for data_b3_ind NCCI %x\n",
764                sc->sc_unit, NCCI);
765
766     } else {
767         if (sc->sc_bchan[bch].bprot == BPROT_RHDLC) {
768             /* HDLC drivers use rx_mbuf */
769
770             sc->sc_bchan[bch].in_mbuf = m_in->m_next;
771             sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
772             m_in->m_next = NULL; /* driver frees */
773
774             (*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
775                 sc->sc_bchan[bch].capi_drvr_linktab->unit);
776
777         } else {
778             /* Telephony drivers use rx_queue */
779
780             if (!_IF_QFULL(&sc->sc_bchan[bch].rx_queue)) {
781                 _IF_ENQUEUE(&sc->sc_bchan[bch].rx_queue, m_in->m_next);
782                 sc->sc_bchan[bch].rxcount += m_in->m_next->m_len;
783                 m_in->m_next = NULL; /* driver frees */
784             }
785
786             (*sc->sc_bchan[bch].capi_drvr_linktab->bch_rx_data_ready)(
787                 sc->sc_bchan[bch].capi_drvr_linktab->unit);
788         }
789     }
790
791     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
792     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
793     msg = capimsg_setu16(msg, CAPI_DATA_B3_RESP);
794     msg = capimsg_setu16(msg, msgid);
795
796     msg = capimsg_setu32(msg, NCCI);
797     msg = capimsg_setu16(msg, handle);
798
799     sc->send(sc, m);
800 }
801
802 /*
803 //  Connection teardown:
804 //  --------------------
805 */
806
807 void capi_disconnect_req(capi_softc_t *sc, call_desc_t *cd)
808 {
809     struct mbuf *m = i4b_Dgetmbuf(8 + 5);
810     u_int8_t *msg;
811     u_int16_t msgid;
812     u_int32_t PLCI;
813
814     if (!m) {
815         printf("capi%d: can't get mbuf for disconnect_req\n", sc->sc_unit);
816         return;
817     }
818
819     sc->sc_bchan[cd->channelid].state = B_DISCONNECT_CONF;
820     ctrl_desc[sc->ctrl_unit].bch_state[cd->channelid] = BCH_ST_RSVD;
821     msgid = sc->sc_bchan[cd->channelid].msgid = sc->sc_msgid++;
822     PLCI = (sc->sc_bchan[cd->channelid].ncci & CAPI_PLCI_MASK);
823
824     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
825     msg = capimsg_setu16(msg, I4BCAPI_APPLID);
826     msg = capimsg_setu16(msg, CAPI_DISCONNECT_REQ);
827     msg = capimsg_setu16(msg, msgid);
828
829     msg = capimsg_setu32(msg, PLCI);
830     msg = capimsg_setu8(msg, 0); /* Additional Info */
831
832     sc->send(sc, m);
833 }
834
835 void capi_disconnect_conf(capi_softc_t *sc, struct mbuf *m_in)
836 {
837     u_int8_t *msg = mtod(m_in, u_int8_t*);
838     call_desc_t *cd;
839     u_int32_t PLCI;
840     int bch;
841
842     msg = capimsg_getu32(msg + 8, &PLCI);
843
844     for (bch = 0; bch < sc->sc_nbch; bch++)
845         if ((sc->sc_bchan[bch].state == B_DISCONNECT_CONF) &&
846             ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
847             break;
848
849     if (bch == sc->sc_nbch) {
850         printf("capi%d: can't find channel for disconnect_conf PLCI %x\n",
851                sc->sc_unit, PLCI);
852         return;
853     }
854
855     cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
856     if (!cd) {
857         printf("capi%d: can't find cd for disconnect_conf PLCI %x\n",
858                sc->sc_unit, PLCI);
859     } else {
860         i4b_l4_disconnect_ind(cd);
861         freecd_by_cd(cd);
862     }
863
864     sc->sc_bchan[bch].state = B_FREE;
865     ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
866 }
867
868 void capi_disconnect_b3_ind(capi_softc_t *sc, struct mbuf *m_in)
869 {
870     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
871     u_int8_t *msg = mtod(m_in, u_int8_t*);
872     u_int16_t applid, msgid;
873     u_int32_t NCCI;
874
875     if (!m) {
876         printf("capi%d: can't get mbuf for disconnect_b3_resp\n", sc->sc_unit);
877         return;
878     }
879
880     msg = capimsg_getu16(msg + 2, &applid);
881     msg = capimsg_getu16(msg + 2, &msgid);
882     msg = capimsg_getu32(msg, &NCCI);
883
884     /* XXX update bchan state? XXX */
885
886     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
887     msg = capimsg_setu16(msg, applid);
888     msg = capimsg_setu16(msg, CAPI_DISCONNECT_B3_RESP);
889     msg = capimsg_setu16(msg, msgid);
890
891     msg = capimsg_setu32(msg, NCCI);
892
893     sc->send(sc, m);
894 }
895
896 void capi_disconnect_ind(capi_softc_t *sc, struct mbuf *m_in)
897 {
898     struct mbuf *m = i4b_Dgetmbuf(8 + 4);
899     u_int8_t *msg = mtod(m_in, u_int8_t*);
900     call_desc_t *cd;
901     u_int16_t applid, msgid;
902     u_int32_t PLCI;
903     u_int16_t Reason;
904     int bch;
905
906     if (!m) {
907         printf("capi%d: can't get mbuf for disconnect_resp\n", sc->sc_unit);
908         return;
909     }
910
911     msg = capimsg_getu16(msg + 2, &applid);
912     msg = capimsg_getu16(msg + 2, &msgid);
913     msg = capimsg_getu32(msg, &PLCI);
914     msg = capimsg_getu16(msg, &Reason);
915
916     for (bch = 0; bch < sc->sc_nbch; bch++)
917         if ((sc->sc_bchan[bch].state != B_FREE) &&
918             ((sc->sc_bchan[bch].ncci & CAPI_PLCI_MASK) == PLCI))
919             break;
920
921     if (bch < sc->sc_nbch) {
922         /* We may not have a bchan assigned if call was ignored. */
923
924         cd = cd_by_cdid(sc->sc_bchan[bch].cdid);
925         sc->sc_bchan[bch].state = B_DISCONNECT_IND;
926     } else cd = NULL;
927
928     if (cd) {
929         if ((Reason & 0xff00) == 0x3400) {
930             SET_CAUSE_TV(cd->cause_in, CAUSET_Q850, (Reason & 0x7f));
931         } else {
932             SET_CAUSE_TV(cd->cause_in, CAUSET_I4B, CAUSE_I4B_NORMAL);
933         }
934
935         i4b_l4_disconnect_ind(cd);
936         freecd_by_cd(cd);
937
938         sc->sc_bchan[bch].state = B_FREE;
939         ctrl_desc[sc->ctrl_unit].bch_state[bch] = BCH_ST_FREE;
940     }
941
942     msg = capimsg_setu16(mtod(m, u_int8_t*), m->m_len);
943     msg = capimsg_setu16(msg, applid);
944     msg = capimsg_setu16(msg, CAPI_DISCONNECT_RESP);
945     msg = capimsg_setu16(msg, msgid);
946
947     msg = capimsg_setu32(msg, PLCI);
948
949     sc->send(sc, m);
950 }