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 static inline unsigned char
66 FlipBits(unsigned char c
, int keylen
)
69 unsigned char bit
= 128;
72 int hunks
= (8 / keylen
);
75 for (i
= 0; i
< hunks
; i
++) {
76 for (j
= 0; j
< keylen
; j
++) {
78 c
|= bit
>> (keylen
- j
- 1);
86 /* isdn_v110_open allocates and initializes private V.110 data
87 * structures and returns a pointer to these.
89 static isdn_v110_stream
*
90 isdn_v110_open(unsigned char key
, int hdrlen
, int maxsize
)
95 if ((v
= kzalloc(sizeof(isdn_v110_stream
), GFP_ATOMIC
)) == NULL
)
99 for (i
= 0; key
& (1 << i
); i
++)
102 v
->nbytes
= 8 / v
->nbits
;
107 v
->OnlineFrame
= V110_OnMatrix_38400
;
108 v
->OfflineFrame
= V110_OffMatrix_38400
;
111 v
->OnlineFrame
= V110_OnMatrix_19200
;
112 v
->OfflineFrame
= V110_OffMatrix_19200
;
115 v
->OnlineFrame
= V110_OnMatrix_9600
;
116 v
->OfflineFrame
= V110_OffMatrix_9600
;
119 v
->framelen
= v
->nbytes
* 10;
125 v
->maxsize
= maxsize
- hdrlen
;
126 if ((v
->encodebuf
= kmalloc(maxsize
, GFP_ATOMIC
)) == NULL
) {
133 /* isdn_v110_close frees private V.110 data structures */
135 isdn_v110_close(isdn_v110_stream
* v
)
139 #ifdef ISDN_V110_DEBUG
140 printk(KERN_DEBUG
"v110 close\n");
148 * ValidHeaderBytes return the number of valid bytes in v->decodebuf
151 ValidHeaderBytes(isdn_v110_stream
* v
)
154 for (i
= 0; (i
< v
->decodelen
) && (i
< v
->nbytes
); i
++)
155 if ((v
->decodebuf
[i
] & v
->key
) != 0)
161 * SyncHeader moves the decodebuf ptr to the next valid header
164 SyncHeader(isdn_v110_stream
* v
)
166 unsigned char *rbuf
= v
->decodebuf
;
167 int len
= v
->decodelen
;
171 for (rbuf
++, len
--; len
> 0; len
--, rbuf
++) /* such den SyncHeader in buf ! */
172 if ((*rbuf
& v
->key
) == 0) /* erstes byte gefunden ? */
175 memcpy(v
->decodebuf
, rbuf
, len
);
178 #ifdef ISDN_V110_DEBUG
179 printk(KERN_DEBUG
"isdn_v110: Header resync\n");
183 /* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
184 len is the number of matrix-lines. len must be a multiple of 10, i.e.
185 only complete matices must be given.
186 From these, netto data is extracted and returned in buf. The return-value
187 is the bytecount of the decoded data.
190 DecodeMatrix(isdn_v110_stream
* v
, unsigned char *m
, int len
, unsigned char *buf
)
195 int introducer
= v
->introducer
;
197 unsigned char b
= v
->b
;
199 while (line
< len
) { /* Are we done with all lines of the matrix? */
200 if ((line
% 10) == 0) { /* the 0. line of the matrix is always 0 ! */
201 if (m
[line
] != 0x00) { /* not 0 ? -> error! */
202 #ifdef ISDN_V110_DEBUG
203 printk(KERN_DEBUG
"isdn_v110: DecodeMatrix, V110 Bad Header\n");
204 /* returning now is not the right thing, though :-( */
207 line
++; /* next line of matrix */
209 } else if ((line
% 10) == 5) { /* in line 5 there's only e-bits ! */
210 if ((m
[line
] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
211 #ifdef ISDN_V110_DEBUG
212 printk(KERN_DEBUG
"isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
213 /* returning now is not the right thing, though :-( */
216 line
++; /* next line */
218 } else if (!introducer
) { /* every byte starts with 10 (stopbit, startbit) */
219 introducer
= (m
[line
] & mbit
) ? 0 : 1; /* current bit of the matrix */
221 if (mbit
> 2) { /* was it the last bit in this line ? */
222 mbit
>>= 1; /* no -> take next */
224 } /* otherwise start with leftmost bit in the next line */
228 } else { /* otherwise we need to set a data bit */
229 if (m
[line
] & mbit
) /* was that bit set in the matrix ? */
230 b
|= dbit
; /* yes -> set it in the data byte */
232 b
&= dbit
- 1; /* no -> clear it in the data byte */
233 if (dbit
< 128) /* is that data byte done ? */
234 dbit
<<= 1; /* no, got the next bit */
235 else { /* data byte is done */
236 buf
[buflen
++] = b
; /* copy byte into the output buffer */
237 introducer
= b
= 0; /* init of the intro sequence and of the data byte */
238 dbit
= 1; /* next we look for the 0th bit */
240 goto next_byte
; /* look for next bit in the matrix */
243 v
->introducer
= introducer
;
246 return buflen
; /* return number of bytes in the output buffer */
250 * DecodeStream receives V.110 coded data from the input stream. It recovers the
252 * The input stream doesn't need to be framed
255 isdn_v110_decode(isdn_v110_stream
* v
, struct sk_buff
*skb
)
260 unsigned char *v110_buf
;
264 printk(KERN_WARNING
"isdn_v110_decode called with NULL skb!\n");
270 /* invalid handle, no chance to proceed */
271 printk(KERN_WARNING
"isdn_v110_decode called with NULL stream!\n");
275 if (v
->decodelen
== 0) /* cache empty? */
276 for (; len
> 0; len
--, rbuf
++) /* scan for SyncHeader in buf */
277 if ((*rbuf
& v
->key
) == 0)
278 break; /* found first byte */
283 /* copy new data to decode-buffer */
284 memcpy(&(v
->decodebuf
[v
->decodelen
]), rbuf
, len
);
287 if (v
->decodelen
< v
->nbytes
) { /* got a new header ? */
289 return NULL
; /* no, try later */
291 if (ValidHeaderBytes(v
) != v
->nbytes
) { /* is that a valid header? */
292 SyncHeader(v
); /* no -> look for header */
295 len
= (v
->decodelen
- (v
->decodelen
% (10 * v
->nbytes
))) / v
->nbytes
;
296 if ((v110_buf
= kmalloc(len
, GFP_ATOMIC
)) == NULL
) {
297 printk(KERN_WARNING
"isdn_v110_decode: Couldn't allocate v110_buf\n");
301 for (i
= 0; i
< len
; i
++) {
303 for (j
= 0; j
< v
->nbytes
; j
++)
304 v110_buf
[i
] |= (v
->decodebuf
[(i
* v
->nbytes
) + j
] & v
->key
) << (8 - ((j
+ 1) * v
->nbits
));
305 v110_buf
[i
] = FlipBits(v110_buf
[i
], v
->nbits
);
307 v
->decodelen
= (v
->decodelen
% (10 * v
->nbytes
));
308 memcpy(v
->decodebuf
, &(v
->decodebuf
[len
* v
->nbytes
]), v
->decodelen
);
310 skb_trim(skb
, DecodeMatrix(v
, v110_buf
, len
, skb
->data
));
320 /* EncodeMatrix takes input data in buf, len is the bytecount.
321 Data is encoded into v110 frames in m. Return value is the number of
322 matrix-lines generated.
325 EncodeMatrix(unsigned char *buf
, int len
, unsigned char *m
, int mlen
)
332 int ibit
[] = {0, 1, 1};
334 while ((i
< len
) && (line
< mlen
)) { /* while we still have input data */
335 switch (line
% 10) { /* in which line of the matrix are we? */
337 m
[line
++] = 0x00; /* line 0 is always 0 */
338 mbit
= 128; /* go on with the 7th bit */
341 m
[line
++] = 0xbf; /* line 5 is always 10111111 */
342 mbit
= 128; /* go on with the 7th bit */
346 printk(KERN_WARNING
"isdn_v110 (EncodeMatrix): buffer full!\n");
350 switch (mbit
) { /* leftmost or rightmost bit ? */
352 line
++; /* rightmost -> go to next line */
354 printk(KERN_WARNING
"isdn_v110 (EncodeMatrix): buffer full!\n");
358 m
[line
] = 128; /* leftmost -> set byte to 1000000 */
359 mbit
= 64; /* current bit in the matrix line */
362 if (introducer
) { /* set 110 sequence ? */
363 introducer
--; /* set on digit less */
364 m
[line
] |= ibit
[introducer
] ? mbit
: 0; /* set corresponding bit */
365 mbit
>>= 1; /* bit of matrix line >> 1 */
366 goto next_bit
; /* and go on there */
367 } /* else push data bits into the matrix! */
368 m
[line
] |= (buf
[i
] & dbit
) ? mbit
: 0; /* set data bit in matrix */
369 if (dbit
== 128) { /* was it the last one? */
370 dbit
= 1; /* then go on with first bit of */
371 i
++; /* next byte in input buffer */
372 if (i
< len
) /* input buffer done ? */
373 introducer
= 3; /* no, write introducer 110 */
374 else { /* input buffer done ! */
375 m
[line
] |= (mbit
- 1) & 0xfe; /* set remaining bits in line to 1 */
378 } else /* not the last data bit */
379 dbit
<<= 1; /* then go to next data bit */
380 mbit
>>= 1; /* go to next bit of matrix */
384 /* if necessary, generate remaining lines of the matrix... */
385 if ((line
) && ((line
+ 10) < mlen
))
386 switch (++line
% 10) {
406 return line
; /* that's how many lines we have */
410 * Build a sync frame.
412 static struct sk_buff
*
413 isdn_v110_sync(isdn_v110_stream
*v
)
418 /* invalid handle, no chance to proceed */
419 printk(KERN_WARNING
"isdn_v110_sync called with NULL stream!\n");
422 if ((skb
= dev_alloc_skb(v
->framelen
+ v
->skbres
))) {
423 skb_reserve(skb
, v
->skbres
);
424 memcpy(skb_put(skb
, v
->framelen
), v
->OfflineFrame
, v
->framelen
);
430 * Build an idle frame.
432 static struct sk_buff
*
433 isdn_v110_idle(isdn_v110_stream
*v
)
438 /* invalid handle, no chance to proceed */
439 printk(KERN_WARNING
"isdn_v110_sync called with NULL stream!\n");
442 if ((skb
= dev_alloc_skb(v
->framelen
+ v
->skbres
))) {
443 skb_reserve(skb
, v
->skbres
);
444 memcpy(skb_put(skb
, v
->framelen
), v
->OnlineFrame
, v
->framelen
);
450 isdn_v110_encode(isdn_v110_stream
* v
, struct sk_buff
*skb
)
461 unsigned char *v110buf
;
463 struct sk_buff
*nskb
;
466 /* invalid handle, no chance to proceed */
467 printk(KERN_WARNING
"isdn_v110_encode called with NULL stream!\n");
471 /* invalid skb, no chance to proceed */
472 printk(KERN_WARNING
"isdn_v110_encode called with NULL skb!\n");
476 nframes
= (rlen
+ 3) / 4;
477 v110buf
= v
->encodebuf
;
478 if ((nframes
* 40) > v
->maxsize
) {
480 rlen
= v
->maxsize
/ 40;
483 if (!(nskb
= dev_alloc_skb(size
+ v
->skbres
+ sizeof(int)))) {
484 printk(KERN_WARNING
"isdn_v110_encode: Couldn't alloc skb\n");
487 skb_reserve(nskb
, v
->skbres
+ sizeof(int));
489 memcpy(skb_put(nskb
, v
->framelen
), v
->OnlineFrame
, v
->framelen
);
490 *((int *)skb_push(nskb
, sizeof(int))) = 0;
493 mlen
= EncodeMatrix(skb
->data
, rlen
, v110buf
, size
);
494 /* now distribute 2 or 4 bits each to the output stream! */
495 rbuf
= skb_put(nskb
, size
);
497 sval1
= 8 - v
->nbits
;
498 sval2
= v
->key
<< sval1
;
499 for (i
= 0; i
< mlen
; i
++) {
500 v110buf
[i
] = FlipBits(v110buf
[i
], v
->nbits
);
501 for (j
= 0; j
< v
->nbytes
; j
++) {
503 *rbuf
++ = ~v
->key
| (((v110buf
[i
] << (j
* v
->nbits
)) & sval2
) >> sval1
);
505 printk(KERN_WARNING
"isdn_v110_encode: buffers full!\n");
512 skb_trim(nskb
, olen
);
513 *((int *)skb_push(nskb
, sizeof(int))) = rlen
;
518 isdn_v110_stat_callback(int idx
, isdn_ctrl
*c
)
520 isdn_v110_stream
*v
= NULL
;
526 switch (c
->command
) {
527 case ISDN_STAT_BSENT
:
528 /* Keep the send-queue of the driver filled
530 * If number of outstanding frames < 3,
531 * send down an Idle-Frame (or an Sync-Frame, if
534 if (!(v
= dev
->v110
[idx
]))
536 atomic_inc(&dev
->v110use
[idx
]);
537 for (i
=0; i
* v
->framelen
< c
->parm
.length
; i
++) {
538 if (v
->skbidle
> 0) {
547 for (i
= v
->skbuser
+ v
->skbidle
; i
< 2; i
++) {
550 skb
= isdn_v110_sync(v
);
552 skb
= isdn_v110_idle(v
);
554 if (dev
->drv
[c
->driver
]->interface
->writebuf_skb(c
->driver
, c
->arg
, 1, skb
) <= 0) {
565 atomic_dec(&dev
->v110use
[idx
]);
570 atomic_inc(&dev
->v110use
[idx
]);
571 if (atomic_dec_and_test(&dev
->v110use
[idx
])) {
572 isdn_v110_close(dev
->v110
[idx
]);
573 dev
->v110
[idx
] = NULL
;
579 case ISDN_STAT_BCONN
:
580 if (dev
->v110emu
[idx
] && (dev
->v110
[idx
] == NULL
)) {
581 int hdrlen
= dev
->drv
[c
->driver
]->interface
->hl_hdrlen
;
582 int maxsize
= dev
->drv
[c
->driver
]->interface
->maxbufsize
;
583 atomic_inc(&dev
->v110use
[idx
]);
584 switch (dev
->v110emu
[idx
]) {
585 case ISDN_PROTO_L2_V11096
:
586 dev
->v110
[idx
] = isdn_v110_open(V110_9600
, hdrlen
, maxsize
);
588 case ISDN_PROTO_L2_V11019
:
589 dev
->v110
[idx
] = isdn_v110_open(V110_19200
, hdrlen
, maxsize
);
591 case ISDN_PROTO_L2_V11038
:
592 dev
->v110
[idx
] = isdn_v110_open(V110_38400
, hdrlen
, maxsize
);
596 if ((v
= dev
->v110
[idx
])) {
597 while (v
->SyncInit
) {
598 struct sk_buff
*skb
= isdn_v110_sync(v
);
599 if (dev
->drv
[c
->driver
]->interface
->writebuf_skb(c
->driver
, c
->arg
, 1, skb
) <= 0) {
601 /* Unable to send, try later */
608 printk(KERN_WARNING
"isdn_v110: Couldn't open stream for chan %d\n", idx
);
609 atomic_dec(&dev
->v110use
[idx
]);