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