1 /* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
3 * Linux ISDN subsystem, V.110 related functions (linklevel).
5 * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
12 #include <linux/string.h>
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
16 #include <linux/delay.h>
18 #include <linux/isdn.h>
19 #include "isdn_v110.h"
21 #undef ISDN_V110_DEBUG
23 char *isdn_v110_revision
= "$Revision: 1.1.2.2 $";
25 #define V110_38400 255
30 * The following data are precoded matrices, online and offline matrix
31 * for 9600, 19200 und 38400, respectively
33 static unsigned char V110_OnMatrix_9600
[] =
34 {0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
35 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd,
36 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
37 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd};
39 static unsigned char V110_OffMatrix_9600
[] =
40 {0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
45 static unsigned char V110_OnMatrix_19200
[] =
46 {0xf0, 0xf0, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7,
47 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7};
49 static unsigned char V110_OffMatrix_19200
[] =
50 {0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
53 static unsigned char V110_OnMatrix_38400
[] =
54 {0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0xfd, 0x7f, 0x7f, 0x7f, 0x7f};
56 static unsigned char V110_OffMatrix_38400
[] =
57 {0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};
60 * FlipBits reorders sequences of keylen bits in one byte.
61 * E.g. source order 7654321 will be converted to 45670123 when keylen = 4,
62 * and to 67452301 when keylen = 2. This is necessary because ordering on
63 * the isdn line is the other way.
65 <<<<<<< HEAD
:drivers
/isdn
/i4l
/isdn_v110
.c
66 static __inline
unsigned char
68 static inline unsigned char
69 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:drivers
/isdn
/i4l
/isdn_v110
.c
70 FlipBits(unsigned char c
, int keylen
)
73 unsigned char bit
= 128;
76 int hunks
= (8 / keylen
);
79 for (i
= 0; i
< hunks
; i
++) {
80 for (j
= 0; j
< keylen
; j
++) {
82 c
|= bit
>> (keylen
- j
- 1);
90 /* isdn_v110_open allocates and initializes private V.110 data
91 * structures and returns a pointer to these.
93 static isdn_v110_stream
*
94 isdn_v110_open(unsigned char key
, int hdrlen
, int maxsize
)
99 if ((v
= kzalloc(sizeof(isdn_v110_stream
), GFP_ATOMIC
)) == NULL
)
103 for (i
= 0; key
& (1 << i
); i
++)
106 v
->nbytes
= 8 / v
->nbits
;
111 v
->OnlineFrame
= V110_OnMatrix_38400
;
112 v
->OfflineFrame
= V110_OffMatrix_38400
;
115 v
->OnlineFrame
= V110_OnMatrix_19200
;
116 v
->OfflineFrame
= V110_OffMatrix_19200
;
119 v
->OnlineFrame
= V110_OnMatrix_9600
;
120 v
->OfflineFrame
= V110_OffMatrix_9600
;
123 v
->framelen
= v
->nbytes
* 10;
129 v
->maxsize
= maxsize
- hdrlen
;
130 if ((v
->encodebuf
= kmalloc(maxsize
, GFP_ATOMIC
)) == NULL
) {
137 /* isdn_v110_close frees private V.110 data structures */
139 isdn_v110_close(isdn_v110_stream
* v
)
143 #ifdef ISDN_V110_DEBUG
144 printk(KERN_DEBUG
"v110 close\n");
152 * ValidHeaderBytes return the number of valid bytes in v->decodebuf
155 ValidHeaderBytes(isdn_v110_stream
* v
)
158 for (i
= 0; (i
< v
->decodelen
) && (i
< v
->nbytes
); i
++)
159 if ((v
->decodebuf
[i
] & v
->key
) != 0)
165 * SyncHeader moves the decodebuf ptr to the next valid header
168 SyncHeader(isdn_v110_stream
* v
)
170 unsigned char *rbuf
= v
->decodebuf
;
171 int len
= v
->decodelen
;
175 for (rbuf
++, len
--; len
> 0; len
--, rbuf
++) /* such den SyncHeader in buf ! */
176 if ((*rbuf
& v
->key
) == 0) /* erstes byte gefunden ? */
179 memcpy(v
->decodebuf
, rbuf
, len
);
182 #ifdef ISDN_V110_DEBUG
183 printk(KERN_DEBUG
"isdn_v110: Header resync\n");
187 /* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
188 len is the number of matrix-lines. len must be a multiple of 10, i.e.
189 only complete matices must be given.
190 From these, netto data is extracted and returned in buf. The return-value
191 is the bytecount of the decoded data.
194 DecodeMatrix(isdn_v110_stream
* v
, unsigned char *m
, int len
, unsigned char *buf
)
199 int introducer
= v
->introducer
;
201 unsigned char b
= v
->b
;
203 while (line
< len
) { /* Are we done with all lines of the matrix? */
204 if ((line
% 10) == 0) { /* the 0. line of the matrix is always 0 ! */
205 if (m
[line
] != 0x00) { /* not 0 ? -> error! */
206 #ifdef ISDN_V110_DEBUG
207 printk(KERN_DEBUG
"isdn_v110: DecodeMatrix, V110 Bad Header\n");
208 /* returning now is not the right thing, though :-( */
211 line
++; /* next line of matrix */
213 } else if ((line
% 10) == 5) { /* in line 5 there's only e-bits ! */
214 if ((m
[line
] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
215 #ifdef ISDN_V110_DEBUG
216 printk(KERN_DEBUG
"isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
217 /* returning now is not the right thing, though :-( */
220 line
++; /* next line */
222 } else if (!introducer
) { /* every byte starts with 10 (stopbit, startbit) */
223 introducer
= (m
[line
] & mbit
) ? 0 : 1; /* current bit of the matrix */
225 if (mbit
> 2) { /* was it the last bit in this line ? */
226 mbit
>>= 1; /* no -> take next */
228 } /* otherwise start with leftmost bit in the next line */
232 } else { /* otherwise we need to set a data bit */
233 if (m
[line
] & mbit
) /* was that bit set in the matrix ? */
234 b
|= dbit
; /* yes -> set it in the data byte */
236 b
&= dbit
- 1; /* no -> clear it in the data byte */
237 if (dbit
< 128) /* is that data byte done ? */
238 dbit
<<= 1; /* no, got the next bit */
239 else { /* data byte is done */
240 buf
[buflen
++] = b
; /* copy byte into the output buffer */
241 introducer
= b
= 0; /* init of the intro sequence and of the data byte */
242 dbit
= 1; /* next we look for the 0th bit */
244 goto next_byte
; /* look for next bit in the matrix */
247 v
->introducer
= introducer
;
250 return buflen
; /* return number of bytes in the output buffer */
254 * DecodeStream receives V.110 coded data from the input stream. It recovers the
256 * The input stream doesn't need to be framed
259 isdn_v110_decode(isdn_v110_stream
* v
, struct sk_buff
*skb
)
264 unsigned char *v110_buf
;
268 printk(KERN_WARNING
"isdn_v110_decode called with NULL skb!\n");
274 /* invalid handle, no chance to proceed */
275 printk(KERN_WARNING
"isdn_v110_decode called with NULL stream!\n");
279 if (v
->decodelen
== 0) /* cache empty? */
280 for (; len
> 0; len
--, rbuf
++) /* scan for SyncHeader in buf */
281 if ((*rbuf
& v
->key
) == 0)
282 break; /* found first byte */
287 /* copy new data to decode-buffer */
288 memcpy(&(v
->decodebuf
[v
->decodelen
]), rbuf
, len
);
291 if (v
->decodelen
< v
->nbytes
) { /* got a new header ? */
293 return NULL
; /* no, try later */
295 if (ValidHeaderBytes(v
) != v
->nbytes
) { /* is that a valid header? */
296 SyncHeader(v
); /* no -> look for header */
299 len
= (v
->decodelen
- (v
->decodelen
% (10 * v
->nbytes
))) / v
->nbytes
;
300 if ((v110_buf
= kmalloc(len
, GFP_ATOMIC
)) == NULL
) {
301 printk(KERN_WARNING
"isdn_v110_decode: Couldn't allocate v110_buf\n");
305 for (i
= 0; i
< len
; i
++) {
307 for (j
= 0; j
< v
->nbytes
; j
++)
308 v110_buf
[i
] |= (v
->decodebuf
[(i
* v
->nbytes
) + j
] & v
->key
) << (8 - ((j
+ 1) * v
->nbits
));
309 v110_buf
[i
] = FlipBits(v110_buf
[i
], v
->nbits
);
311 v
->decodelen
= (v
->decodelen
% (10 * v
->nbytes
));
312 memcpy(v
->decodebuf
, &(v
->decodebuf
[len
* v
->nbytes
]), v
->decodelen
);
314 skb_trim(skb
, DecodeMatrix(v
, v110_buf
, len
, skb
->data
));
324 /* EncodeMatrix takes input data in buf, len is the bytecount.
325 Data is encoded into v110 frames in m. Return value is the number of
326 matrix-lines generated.
329 EncodeMatrix(unsigned char *buf
, int len
, unsigned char *m
, int mlen
)
336 int ibit
[] = {0, 1, 1};
338 while ((i
< len
) && (line
< mlen
)) { /* while we still have input data */
339 switch (line
% 10) { /* in which line of the matrix are we? */
341 m
[line
++] = 0x00; /* line 0 is always 0 */
342 mbit
= 128; /* go on with the 7th bit */
345 m
[line
++] = 0xbf; /* line 5 is always 10111111 */
346 mbit
= 128; /* go on with the 7th bit */
350 printk(KERN_WARNING
"isdn_v110 (EncodeMatrix): buffer full!\n");
354 switch (mbit
) { /* leftmost or rightmost bit ? */
356 line
++; /* rightmost -> go to next line */
358 printk(KERN_WARNING
"isdn_v110 (EncodeMatrix): buffer full!\n");
362 m
[line
] = 128; /* leftmost -> set byte to 1000000 */
363 mbit
= 64; /* current bit in the matrix line */
366 if (introducer
) { /* set 110 sequence ? */
367 introducer
--; /* set on digit less */
368 m
[line
] |= ibit
[introducer
] ? mbit
: 0; /* set corresponding bit */
369 mbit
>>= 1; /* bit of matrix line >> 1 */
370 goto next_bit
; /* and go on there */
371 } /* else push data bits into the matrix! */
372 m
[line
] |= (buf
[i
] & dbit
) ? mbit
: 0; /* set data bit in matrix */
373 if (dbit
== 128) { /* was it the last one? */
374 dbit
= 1; /* then go on with first bit of */
375 i
++; /* next byte in input buffer */
376 if (i
< len
) /* input buffer done ? */
377 introducer
= 3; /* no, write introducer 110 */
378 else { /* input buffer done ! */
379 m
[line
] |= (mbit
- 1) & 0xfe; /* set remaining bits in line to 1 */
382 } else /* not the last data bit */
383 dbit
<<= 1; /* then go to next data bit */
384 mbit
>>= 1; /* go to next bit of matrix */
388 /* if necessary, generate remaining lines of the matrix... */
389 if ((line
) && ((line
+ 10) < mlen
))
390 switch (++line
% 10) {
410 return line
; /* that's how many lines we have */
414 * Build a sync frame.
416 static struct sk_buff
*
417 isdn_v110_sync(isdn_v110_stream
*v
)
422 /* invalid handle, no chance to proceed */
423 printk(KERN_WARNING
"isdn_v110_sync called with NULL stream!\n");
426 if ((skb
= dev_alloc_skb(v
->framelen
+ v
->skbres
))) {
427 skb_reserve(skb
, v
->skbres
);
428 memcpy(skb_put(skb
, v
->framelen
), v
->OfflineFrame
, v
->framelen
);
434 * Build an idle frame.
436 static struct sk_buff
*
437 isdn_v110_idle(isdn_v110_stream
*v
)
442 /* invalid handle, no chance to proceed */
443 printk(KERN_WARNING
"isdn_v110_sync called with NULL stream!\n");
446 if ((skb
= dev_alloc_skb(v
->framelen
+ v
->skbres
))) {
447 skb_reserve(skb
, v
->skbres
);
448 memcpy(skb_put(skb
, v
->framelen
), v
->OnlineFrame
, v
->framelen
);
454 isdn_v110_encode(isdn_v110_stream
* v
, struct sk_buff
*skb
)
465 unsigned char *v110buf
;
467 struct sk_buff
*nskb
;
470 /* invalid handle, no chance to proceed */
471 printk(KERN_WARNING
"isdn_v110_encode called with NULL stream!\n");
475 /* invalid skb, no chance to proceed */
476 printk(KERN_WARNING
"isdn_v110_encode called with NULL skb!\n");
480 nframes
= (rlen
+ 3) / 4;
481 v110buf
= v
->encodebuf
;
482 if ((nframes
* 40) > v
->maxsize
) {
484 rlen
= v
->maxsize
/ 40;
487 if (!(nskb
= dev_alloc_skb(size
+ v
->skbres
+ sizeof(int)))) {
488 printk(KERN_WARNING
"isdn_v110_encode: Couldn't alloc skb\n");
491 skb_reserve(nskb
, v
->skbres
+ sizeof(int));
493 memcpy(skb_put(nskb
, v
->framelen
), v
->OnlineFrame
, v
->framelen
);
494 *((int *)skb_push(nskb
, sizeof(int))) = 0;
497 mlen
= EncodeMatrix(skb
->data
, rlen
, v110buf
, size
);
498 /* now distribute 2 or 4 bits each to the output stream! */
499 rbuf
= skb_put(nskb
, size
);
501 sval1
= 8 - v
->nbits
;
502 sval2
= v
->key
<< sval1
;
503 for (i
= 0; i
< mlen
; i
++) {
504 v110buf
[i
] = FlipBits(v110buf
[i
], v
->nbits
);
505 for (j
= 0; j
< v
->nbytes
; j
++) {
507 *rbuf
++ = ~v
->key
| (((v110buf
[i
] << (j
* v
->nbits
)) & sval2
) >> sval1
);
509 printk(KERN_WARNING
"isdn_v110_encode: buffers full!\n");
516 skb_trim(nskb
, olen
);
517 *((int *)skb_push(nskb
, sizeof(int))) = rlen
;
522 isdn_v110_stat_callback(int idx
, isdn_ctrl
*c
)
524 isdn_v110_stream
*v
= NULL
;
530 switch (c
->command
) {
531 case ISDN_STAT_BSENT
:
532 /* Keep the send-queue of the driver filled
534 * If number of outstanding frames < 3,
535 * send down an Idle-Frame (or an Sync-Frame, if
538 if (!(v
= dev
->v110
[idx
]))
540 atomic_inc(&dev
->v110use
[idx
]);
541 for (i
=0; i
* v
->framelen
< c
->parm
.length
; i
++) {
542 if (v
->skbidle
> 0) {
551 for (i
= v
->skbuser
+ v
->skbidle
; i
< 2; i
++) {
554 skb
= isdn_v110_sync(v
);
556 skb
= isdn_v110_idle(v
);
558 if (dev
->drv
[c
->driver
]->interface
->writebuf_skb(c
->driver
, c
->arg
, 1, skb
) <= 0) {
569 atomic_dec(&dev
->v110use
[idx
]);
574 atomic_inc(&dev
->v110use
[idx
]);
575 if (atomic_dec_and_test(&dev
->v110use
[idx
])) {
576 isdn_v110_close(dev
->v110
[idx
]);
577 dev
->v110
[idx
] = NULL
;
583 case ISDN_STAT_BCONN
:
584 if (dev
->v110emu
[idx
] && (dev
->v110
[idx
] == NULL
)) {
585 int hdrlen
= dev
->drv
[c
->driver
]->interface
->hl_hdrlen
;
586 int maxsize
= dev
->drv
[c
->driver
]->interface
->maxbufsize
;
587 atomic_inc(&dev
->v110use
[idx
]);
588 switch (dev
->v110emu
[idx
]) {
589 case ISDN_PROTO_L2_V11096
:
590 dev
->v110
[idx
] = isdn_v110_open(V110_9600
, hdrlen
, maxsize
);
592 case ISDN_PROTO_L2_V11019
:
593 dev
->v110
[idx
] = isdn_v110_open(V110_19200
, hdrlen
, maxsize
);
595 case ISDN_PROTO_L2_V11038
:
596 dev
->v110
[idx
] = isdn_v110_open(V110_38400
, hdrlen
, maxsize
);
600 if ((v
= dev
->v110
[idx
])) {
601 while (v
->SyncInit
) {
602 struct sk_buff
*skb
= isdn_v110_sync(v
);
603 if (dev
->drv
[c
->driver
]->interface
->writebuf_skb(c
->driver
, c
->arg
, 1, skb
) <= 0) {
605 /* Unable to send, try later */
612 printk(KERN_WARNING
"isdn_v110: Couldn't open stream for chan %d\n", idx
);
613 atomic_dec(&dev
->v110use
[idx
]);