diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/pcbit/capi.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/isdn/pcbit/capi.c')
-rw-r--r-- | drivers/isdn/pcbit/capi.c | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c new file mode 100644 index 000000000000..29eb03a8c29d --- /dev/null +++ b/drivers/isdn/pcbit/capi.c | |||
@@ -0,0 +1,663 @@ | |||
1 | /* | ||
2 | * CAPI encoder/decoder for | ||
3 | * Portugal Telecom CAPI 2.0 | ||
4 | * | ||
5 | * Copyright (C) 1996 Universidade de Lisboa | ||
6 | * | ||
7 | * Written by Pedro Roque Marques (roque@di.fc.ul.pt) | ||
8 | * | ||
9 | * This software may be used and distributed according to the terms of | ||
10 | * the GNU General Public License, incorporated herein by reference. | ||
11 | * | ||
12 | * Not compatible with the AVM Gmbh. CAPI 2.0 | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | /* | ||
17 | * Documentation: | ||
18 | * - "Common ISDN API - Perfil Português - Versão 2.1", | ||
19 | * Telecom Portugal, Fev 1992. | ||
20 | * - "Common ISDN API - Especificação de protocolos para | ||
21 | * acesso aos canais B", Inesc, Jan 1994. | ||
22 | */ | ||
23 | |||
24 | /* | ||
25 | * TODO: better decoding of Information Elements | ||
26 | * for debug purposes mainly | ||
27 | * encode our number in CallerPN and ConnectedPN | ||
28 | */ | ||
29 | |||
30 | #include <linux/sched.h> | ||
31 | #include <linux/string.h> | ||
32 | #include <linux/kernel.h> | ||
33 | |||
34 | #include <linux/types.h> | ||
35 | #include <linux/slab.h> | ||
36 | #include <linux/mm.h> | ||
37 | |||
38 | #include <linux/skbuff.h> | ||
39 | |||
40 | #include <asm/io.h> | ||
41 | #include <asm/string.h> | ||
42 | |||
43 | #include <linux/isdnif.h> | ||
44 | |||
45 | #include "pcbit.h" | ||
46 | #include "edss1.h" | ||
47 | #include "capi.h" | ||
48 | |||
49 | |||
50 | /* | ||
51 | * Encoding of CAPI messages | ||
52 | * | ||
53 | */ | ||
54 | |||
55 | int capi_conn_req(const char * calledPN, struct sk_buff **skb, int proto) | ||
56 | { | ||
57 | ushort len; | ||
58 | |||
59 | /* | ||
60 | * length | ||
61 | * AppInfoMask - 2 | ||
62 | * BC0 - 3 | ||
63 | * BC1 - 1 | ||
64 | * Chan - 2 | ||
65 | * Keypad - 1 | ||
66 | * CPN - 1 | ||
67 | * CPSA - 1 | ||
68 | * CalledPN - 2 + strlen | ||
69 | * CalledPSA - 1 | ||
70 | * rest... - 4 | ||
71 | * ---------------- | ||
72 | * Total 18 + strlen | ||
73 | */ | ||
74 | |||
75 | len = 18 + strlen(calledPN); | ||
76 | |||
77 | if (proto == ISDN_PROTO_L2_TRANS) | ||
78 | len++; | ||
79 | |||
80 | if ((*skb = dev_alloc_skb(len)) == NULL) { | ||
81 | |||
82 | printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n"); | ||
83 | return -1; | ||
84 | } | ||
85 | |||
86 | /* InfoElmMask */ | ||
87 | *((ushort*) skb_put(*skb, 2)) = AppInfoMask; | ||
88 | |||
89 | if (proto == ISDN_PROTO_L2_TRANS) | ||
90 | { | ||
91 | /* Bearer Capability - Mandatory*/ | ||
92 | *(skb_put(*skb, 1)) = 3; /* BC0.Length */ | ||
93 | *(skb_put(*skb, 1)) = 0x80; /* Speech */ | ||
94 | *(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */ | ||
95 | *(skb_put(*skb, 1)) = 0x23; /* A-law */ | ||
96 | } | ||
97 | else | ||
98 | { | ||
99 | /* Bearer Capability - Mandatory*/ | ||
100 | *(skb_put(*skb, 1)) = 2; /* BC0.Length */ | ||
101 | *(skb_put(*skb, 1)) = 0x88; /* Digital Information */ | ||
102 | *(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 */ | ||
103 | } | ||
104 | |||
105 | /* Bearer Capability - Optional*/ | ||
106 | *(skb_put(*skb, 1)) = 0; /* BC1.Length = 0 */ | ||
107 | |||
108 | *(skb_put(*skb, 1)) = 1; /* ChannelID.Length = 1 */ | ||
109 | *(skb_put(*skb, 1)) = 0x83; /* Basic Interface - Any Channel */ | ||
110 | |||
111 | *(skb_put(*skb, 1)) = 0; /* Keypad.Length = 0 */ | ||
112 | |||
113 | |||
114 | *(skb_put(*skb, 1)) = 0; /* CallingPN.Length = 0 */ | ||
115 | *(skb_put(*skb, 1)) = 0; /* CallingPSA.Length = 0 */ | ||
116 | |||
117 | /* Called Party Number */ | ||
118 | *(skb_put(*skb, 1)) = strlen(calledPN) + 1; | ||
119 | *(skb_put(*skb, 1)) = 0x81; | ||
120 | memcpy(skb_put(*skb, strlen(calledPN)), calledPN, strlen(calledPN)); | ||
121 | |||
122 | /* '#' */ | ||
123 | |||
124 | *(skb_put(*skb, 1)) = 0; /* CalledPSA.Length = 0 */ | ||
125 | |||
126 | /* LLC.Length = 0; */ | ||
127 | /* HLC0.Length = 0; */ | ||
128 | /* HLC1.Length = 0; */ | ||
129 | /* UTUS.Length = 0; */ | ||
130 | memset(skb_put(*skb, 4), 0, 4); | ||
131 | |||
132 | return len; | ||
133 | } | ||
134 | |||
135 | int capi_conn_resp(struct pcbit_chan* chan, struct sk_buff **skb) | ||
136 | { | ||
137 | |||
138 | if ((*skb = dev_alloc_skb(5)) == NULL) { | ||
139 | |||
140 | printk(KERN_WARNING "capi_conn_resp: alloc_skb failed\n"); | ||
141 | return -1; | ||
142 | } | ||
143 | |||
144 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
145 | *(skb_put(*skb, 1)) = 0x01; /* ACCEPT_CALL */ | ||
146 | *(skb_put(*skb, 1)) = 0; | ||
147 | *(skb_put(*skb, 1)) = 0; | ||
148 | |||
149 | return 5; | ||
150 | } | ||
151 | |||
152 | int capi_conn_active_req(struct pcbit_chan* chan, struct sk_buff **skb) | ||
153 | { | ||
154 | /* | ||
155 | * 8 bytes | ||
156 | */ | ||
157 | |||
158 | if ((*skb = dev_alloc_skb(8)) == NULL) { | ||
159 | |||
160 | printk(KERN_WARNING "capi_conn_active_req: alloc_skb failed\n"); | ||
161 | return -1; | ||
162 | } | ||
163 | |||
164 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
165 | |||
166 | #ifdef DEBUG | ||
167 | printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); | ||
168 | #endif | ||
169 | |||
170 | *(skb_put(*skb, 1)) = 0; /* BC.Length = 0; */ | ||
171 | *(skb_put(*skb, 1)) = 0; /* ConnectedPN.Length = 0 */ | ||
172 | *(skb_put(*skb, 1)) = 0; /* PSA.Length */ | ||
173 | *(skb_put(*skb, 1)) = 0; /* LLC.Length = 0; */ | ||
174 | *(skb_put(*skb, 1)) = 0; /* HLC.Length = 0; */ | ||
175 | *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ | ||
176 | |||
177 | return 8; | ||
178 | } | ||
179 | |||
180 | int capi_conn_active_resp(struct pcbit_chan* chan, struct sk_buff **skb) | ||
181 | { | ||
182 | /* | ||
183 | * 2 bytes | ||
184 | */ | ||
185 | |||
186 | if ((*skb = dev_alloc_skb(2)) == NULL) { | ||
187 | |||
188 | printk(KERN_WARNING "capi_conn_active_resp: alloc_skb failed\n"); | ||
189 | return -1; | ||
190 | } | ||
191 | |||
192 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
193 | |||
194 | return 2; | ||
195 | } | ||
196 | |||
197 | |||
198 | int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb, | ||
199 | int outgoing) | ||
200 | { | ||
201 | |||
202 | /* | ||
203 | * 18 bytes | ||
204 | */ | ||
205 | |||
206 | if ((*skb = dev_alloc_skb(18)) == NULL) { | ||
207 | |||
208 | printk(KERN_WARNING "capi_select_proto_req: alloc_skb failed\n"); | ||
209 | return -1; | ||
210 | } | ||
211 | |||
212 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
213 | |||
214 | /* Layer2 protocol */ | ||
215 | |||
216 | switch (chan->proto) { | ||
217 | case ISDN_PROTO_L2_X75I: | ||
218 | *(skb_put(*skb, 1)) = 0x05; /* LAPB */ | ||
219 | break; | ||
220 | case ISDN_PROTO_L2_HDLC: | ||
221 | *(skb_put(*skb, 1)) = 0x02; | ||
222 | break; | ||
223 | case ISDN_PROTO_L2_TRANS: | ||
224 | /* | ||
225 | * Voice (a-law) | ||
226 | */ | ||
227 | *(skb_put(*skb, 1)) = 0x06; | ||
228 | break; | ||
229 | default: | ||
230 | #ifdef DEBUG | ||
231 | printk(KERN_DEBUG "Transparent\n"); | ||
232 | #endif | ||
233 | *(skb_put(*skb, 1)) = 0x03; | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | *(skb_put(*skb, 1)) = (outgoing ? 0x02 : 0x42); /* Don't ask */ | ||
238 | *(skb_put(*skb, 1)) = 0x00; | ||
239 | |||
240 | *((ushort *) skb_put(*skb, 2)) = MRU; | ||
241 | |||
242 | |||
243 | *(skb_put(*skb, 1)) = 0x08; /* Modulo */ | ||
244 | *(skb_put(*skb, 1)) = 0x07; /* Max Window */ | ||
245 | |||
246 | *(skb_put(*skb, 1)) = 0x01; /* No Layer3 Protocol */ | ||
247 | |||
248 | /* | ||
249 | * 2 - layer3 MTU [10] | ||
250 | * - Modulo [12] | ||
251 | * - Window | ||
252 | * - layer1 proto [14] | ||
253 | * - bitrate | ||
254 | * - sub-channel [16] | ||
255 | * - layer1dataformat [17] | ||
256 | */ | ||
257 | |||
258 | memset(skb_put(*skb, 8), 0, 8); | ||
259 | |||
260 | return 18; | ||
261 | } | ||
262 | |||
263 | |||
264 | int capi_activate_transp_req(struct pcbit_chan *chan, struct sk_buff **skb) | ||
265 | { | ||
266 | |||
267 | if ((*skb = dev_alloc_skb(7)) == NULL) { | ||
268 | |||
269 | printk(KERN_WARNING "capi_activate_transp_req: alloc_skb failed\n"); | ||
270 | return -1; | ||
271 | } | ||
272 | |||
273 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
274 | |||
275 | |||
276 | *(skb_put(*skb, 1)) = chan->layer2link; /* Layer2 id */ | ||
277 | *(skb_put(*skb, 1)) = 0x00; /* Transmit by default */ | ||
278 | |||
279 | *((ushort *) skb_put(*skb, 2)) = MRU; | ||
280 | |||
281 | *(skb_put(*skb, 1)) = 0x01; /* Enables reception*/ | ||
282 | |||
283 | return 7; | ||
284 | } | ||
285 | |||
286 | int capi_tdata_req(struct pcbit_chan* chan, struct sk_buff *skb) | ||
287 | { | ||
288 | ushort data_len; | ||
289 | |||
290 | |||
291 | /* | ||
292 | * callref - 2 | ||
293 | * layer2link - 1 | ||
294 | * wBlockLength - 2 | ||
295 | * data - 4 | ||
296 | * sernum - 1 | ||
297 | */ | ||
298 | |||
299 | data_len = skb->len; | ||
300 | |||
301 | if(skb_headroom(skb) < 10) | ||
302 | { | ||
303 | printk(KERN_CRIT "No headspace (%u) on headroom %p for capi header\n", skb_headroom(skb), skb); | ||
304 | } | ||
305 | else | ||
306 | { | ||
307 | skb_push(skb, 10); | ||
308 | } | ||
309 | |||
310 | *((u16 *) (skb->data)) = chan->callref; | ||
311 | skb->data[2] = chan->layer2link; | ||
312 | *((u16 *) (skb->data + 3)) = data_len; | ||
313 | |||
314 | chan->s_refnum = (chan->s_refnum + 1) % 8; | ||
315 | *((u32 *) (skb->data + 5)) = chan->s_refnum; | ||
316 | |||
317 | skb->data[9] = 0; /* HDLC frame number */ | ||
318 | |||
319 | return 10; | ||
320 | } | ||
321 | |||
322 | int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff ** skb) | ||
323 | |||
324 | { | ||
325 | if ((*skb = dev_alloc_skb(4)) == NULL) { | ||
326 | |||
327 | printk(KERN_WARNING "capi_tdata_resp: alloc_skb failed\n"); | ||
328 | return -1; | ||
329 | } | ||
330 | |||
331 | *((ushort*) skb_put(*skb, 2) ) = chan->callref; | ||
332 | |||
333 | *(skb_put(*skb, 1)) = chan->layer2link; | ||
334 | *(skb_put(*skb, 1)) = chan->r_refnum; | ||
335 | |||
336 | return (*skb)->len; | ||
337 | } | ||
338 | |||
339 | int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause) | ||
340 | { | ||
341 | |||
342 | if ((*skb = dev_alloc_skb(6)) == NULL) { | ||
343 | |||
344 | printk(KERN_WARNING "capi_disc_req: alloc_skb failed\n"); | ||
345 | return -1; | ||
346 | } | ||
347 | |||
348 | *((ushort*) skb_put(*skb, 2) ) = callref; | ||
349 | |||
350 | *(skb_put(*skb, 1)) = 2; /* Cause.Length = 2; */ | ||
351 | *(skb_put(*skb, 1)) = 0x80; | ||
352 | *(skb_put(*skb, 1)) = 0x80 | cause; | ||
353 | |||
354 | /* | ||
355 | * Change it: we should send 'Sic transit gloria Mundi' here ;-) | ||
356 | */ | ||
357 | |||
358 | *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ | ||
359 | |||
360 | return 6; | ||
361 | } | ||
362 | |||
363 | int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb) | ||
364 | { | ||
365 | if ((*skb = dev_alloc_skb(2)) == NULL) { | ||
366 | |||
367 | printk(KERN_WARNING "capi_disc_resp: alloc_skb failed\n"); | ||
368 | return -1; | ||
369 | } | ||
370 | |||
371 | *((ushort*) skb_put(*skb, 2)) = chan->callref; | ||
372 | |||
373 | return 2; | ||
374 | } | ||
375 | |||
376 | |||
377 | /* | ||
378 | * Decoding of CAPI messages | ||
379 | * | ||
380 | */ | ||
381 | |||
382 | int capi_decode_conn_ind(struct pcbit_chan * chan, | ||
383 | struct sk_buff *skb, | ||
384 | struct callb_data *info) | ||
385 | { | ||
386 | int CIlen, len; | ||
387 | |||
388 | /* Call Reference [CAPI] */ | ||
389 | chan->callref = *((ushort*) skb->data); | ||
390 | skb_pull(skb, 2); | ||
391 | |||
392 | #ifdef DEBUG | ||
393 | printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); | ||
394 | #endif | ||
395 | |||
396 | /* Channel Identification */ | ||
397 | |||
398 | /* Expect | ||
399 | Len = 1 | ||
400 | Octect 3 = 0100 10CC - [ 7 Basic, 4 , 2-1 chan ] | ||
401 | */ | ||
402 | |||
403 | CIlen = skb->data[0]; | ||
404 | #ifdef DEBUG | ||
405 | if (CIlen == 1) { | ||
406 | |||
407 | if ( ((skb->data[1]) & 0xFC) == 0x48 ) | ||
408 | printk(KERN_DEBUG "decode_conn_ind: chan ok\n"); | ||
409 | printk(KERN_DEBUG "phyChan = %d\n", skb->data[1] & 0x03); | ||
410 | } | ||
411 | else | ||
412 | printk(KERN_DEBUG "conn_ind: CIlen = %d\n", CIlen); | ||
413 | #endif | ||
414 | skb_pull(skb, CIlen + 1); | ||
415 | |||
416 | /* Calling Party Number */ | ||
417 | /* An "additional service" as far as Portugal Telecom is concerned */ | ||
418 | |||
419 | len = skb->data[0]; | ||
420 | |||
421 | if (len > 0) { | ||
422 | int count = 1; | ||
423 | |||
424 | #ifdef DEBUG | ||
425 | printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]); | ||
426 | #endif | ||
427 | if ((skb->data[1] & 0x80) == 0) | ||
428 | count = 2; | ||
429 | |||
430 | if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC))) | ||
431 | return -1; | ||
432 | |||
433 | memcpy(info->data.setup.CallingPN, skb->data + count + 1, | ||
434 | len - count); | ||
435 | info->data.setup.CallingPN[len - count] = 0; | ||
436 | |||
437 | } | ||
438 | else { | ||
439 | info->data.setup.CallingPN = NULL; | ||
440 | printk(KERN_DEBUG "NULL CallingPN\n"); | ||
441 | } | ||
442 | |||
443 | skb_pull(skb, len + 1); | ||
444 | |||
445 | /* Calling Party Subaddress */ | ||
446 | skb_pull(skb, skb->data[0] + 1); | ||
447 | |||
448 | /* Called Party Number */ | ||
449 | |||
450 | len = skb->data[0]; | ||
451 | |||
452 | if (len > 0) { | ||
453 | int count = 1; | ||
454 | |||
455 | if ((skb->data[1] & 0x80) == 0) | ||
456 | count = 2; | ||
457 | |||
458 | if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC))) | ||
459 | return -1; | ||
460 | |||
461 | memcpy(info->data.setup.CalledPN, skb->data + count + 1, | ||
462 | len - count); | ||
463 | info->data.setup.CalledPN[len - count] = 0; | ||
464 | |||
465 | } | ||
466 | else { | ||
467 | info->data.setup.CalledPN = NULL; | ||
468 | printk(KERN_DEBUG "NULL CalledPN\n"); | ||
469 | } | ||
470 | |||
471 | skb_pull(skb, len + 1); | ||
472 | |||
473 | /* Called Party Subaddress */ | ||
474 | skb_pull(skb, skb->data[0] + 1); | ||
475 | |||
476 | /* LLC */ | ||
477 | skb_pull(skb, skb->data[0] + 1); | ||
478 | |||
479 | /* HLC */ | ||
480 | skb_pull(skb, skb->data[0] + 1); | ||
481 | |||
482 | /* U2U */ | ||
483 | skb_pull(skb, skb->data[0] + 1); | ||
484 | |||
485 | return 0; | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * returns errcode | ||
490 | */ | ||
491 | |||
492 | int capi_decode_conn_conf(struct pcbit_chan * chan, struct sk_buff *skb, | ||
493 | int *complete) | ||
494 | { | ||
495 | int errcode; | ||
496 | |||
497 | chan->callref = *((ushort *) skb->data); /* Update CallReference */ | ||
498 | skb_pull(skb, 2); | ||
499 | |||
500 | errcode = *((ushort *) skb->data); /* read errcode */ | ||
501 | skb_pull(skb, 2); | ||
502 | |||
503 | *complete = *(skb->data); | ||
504 | skb_pull(skb, 1); | ||
505 | |||
506 | /* FIX ME */ | ||
507 | /* This is actually a firmware bug */ | ||
508 | if (!*complete) | ||
509 | { | ||
510 | printk(KERN_DEBUG "complete=%02x\n", *complete); | ||
511 | *complete = 1; | ||
512 | } | ||
513 | |||
514 | |||
515 | /* Optional Bearer Capability */ | ||
516 | skb_pull(skb, *(skb->data) + 1); | ||
517 | |||
518 | /* Channel Identification */ | ||
519 | skb_pull(skb, *(skb->data) + 1); | ||
520 | |||
521 | /* High Layer Compatibility follows */ | ||
522 | skb_pull(skb, *(skb->data) + 1); | ||
523 | |||
524 | return errcode; | ||
525 | } | ||
526 | |||
527 | int capi_decode_conn_actv_ind(struct pcbit_chan * chan, struct sk_buff *skb) | ||
528 | { | ||
529 | ushort len; | ||
530 | #ifdef DEBUG | ||
531 | char str[32]; | ||
532 | #endif | ||
533 | |||
534 | /* Yet Another Bearer Capability */ | ||
535 | skb_pull(skb, *(skb->data) + 1); | ||
536 | |||
537 | |||
538 | /* Connected Party Number */ | ||
539 | len=*(skb->data); | ||
540 | |||
541 | #ifdef DEBUG | ||
542 | if (len > 1 && len < 31) { | ||
543 | memcpy(str, skb->data + 2, len - 1); | ||
544 | str[len] = 0; | ||
545 | printk(KERN_DEBUG "Connected Party Number: %s\n", str); | ||
546 | } | ||
547 | else | ||
548 | printk(KERN_DEBUG "actv_ind CPN len = %d\n", len); | ||
549 | #endif | ||
550 | |||
551 | skb_pull(skb, len + 1); | ||
552 | |||
553 | /* Connected Subaddress */ | ||
554 | skb_pull(skb, *(skb->data) + 1); | ||
555 | |||
556 | /* Low Layer Capability */ | ||
557 | skb_pull(skb, *(skb->data) + 1); | ||
558 | |||
559 | /* High Layer Capability */ | ||
560 | skb_pull(skb, *(skb->data) + 1); | ||
561 | |||
562 | return 0; | ||
563 | } | ||
564 | |||
565 | int capi_decode_conn_actv_conf(struct pcbit_chan * chan, struct sk_buff *skb) | ||
566 | { | ||
567 | ushort errcode; | ||
568 | |||
569 | errcode = *((ushort*) skb->data); | ||
570 | skb_pull(skb, 2); | ||
571 | |||
572 | /* Channel Identification | ||
573 | skb_pull(skb, skb->data[0] + 1); | ||
574 | */ | ||
575 | return errcode; | ||
576 | } | ||
577 | |||
578 | |||
579 | int capi_decode_sel_proto_conf(struct pcbit_chan *chan, struct sk_buff *skb) | ||
580 | { | ||
581 | ushort errcode; | ||
582 | |||
583 | chan->layer2link = *(skb->data); | ||
584 | skb_pull(skb, 1); | ||
585 | |||
586 | errcode = *((ushort*) skb->data); | ||
587 | skb_pull(skb, 2); | ||
588 | |||
589 | return errcode; | ||
590 | } | ||
591 | |||
592 | int capi_decode_actv_trans_conf(struct pcbit_chan *chan, struct sk_buff *skb) | ||
593 | { | ||
594 | ushort errcode; | ||
595 | |||
596 | if (chan->layer2link != *(skb->data) ) | ||
597 | printk("capi_decode_actv_trans_conf: layer2link doesn't match\n"); | ||
598 | |||
599 | skb_pull(skb, 1); | ||
600 | |||
601 | errcode = *((ushort*) skb->data); | ||
602 | skb_pull(skb, 2); | ||
603 | |||
604 | return errcode; | ||
605 | } | ||
606 | |||
607 | int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb) | ||
608 | { | ||
609 | ushort len; | ||
610 | #ifdef DEBUG | ||
611 | int i; | ||
612 | #endif | ||
613 | /* Cause */ | ||
614 | |||
615 | len = *(skb->data); | ||
616 | skb_pull(skb, 1); | ||
617 | |||
618 | #ifdef DEBUG | ||
619 | |||
620 | for (i=0; i<len; i++) | ||
621 | printk(KERN_DEBUG "Cause Octect %d: %02x\n", i+3, | ||
622 | *(skb->data + i)); | ||
623 | #endif | ||
624 | |||
625 | skb_pull(skb, len); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | |||
630 | int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb) | ||
631 | { | ||
632 | ushort errcode; | ||
633 | |||
634 | errcode = *((ushort*) skb->data); | ||
635 | skb_pull(skb, 2); | ||
636 | |||
637 | return errcode; | ||
638 | } | ||
639 | |||
640 | #ifdef DEBUG | ||
641 | int capi_decode_debug_188(u_char *hdr, ushort hdrlen) | ||
642 | { | ||
643 | char str[64]; | ||
644 | int len; | ||
645 | |||
646 | len = hdr[0]; | ||
647 | |||
648 | if (len < 64 && len == hdrlen - 1) { | ||
649 | memcpy(str, hdr + 1, hdrlen - 1); | ||
650 | str[hdrlen - 1] = 0; | ||
651 | printk("%s\n", str); | ||
652 | } | ||
653 | else | ||
654 | printk("debug message incorrect\n"); | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | #endif | ||
659 | |||
660 | |||
661 | |||
662 | |||
663 | |||