diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-02-15 02:15:32 +0000 |
commit | 86464aed71025541805e7b1515541aee89879e33 (patch) | |
tree | e01a457a4912a8553bc65524aa3125d51f29f810 /net/irda/irlap_comp.c | |
parent | 88f99939ecc6a95a79614574cb7d95ffccfc3466 (diff) |
Merge with Linux 2.2.1.
Diffstat (limited to 'net/irda/irlap_comp.c')
-rw-r--r-- | net/irda/irlap_comp.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/net/irda/irlap_comp.c b/net/irda/irlap_comp.c new file mode 100644 index 000000000..d2e876be9 --- /dev/null +++ b/net/irda/irlap_comp.c @@ -0,0 +1,351 @@ +/********************************************************************* + * + * Filename: irlap_comp.c + * Version: + * Description: + * Status: Experimental. + * Author: Dag Brattli <dagb@cs.uit.no> + * Created at: Fri Oct 9 09:18:07 1998 + * Modified at: Mon Dec 14 11:55:27 1998 + * Modified by: Dag Brattli <dagb@cs.uit.no> + * Sources: ppp.c, isdn_ppp.c + * + * Copyright (c) 1998 Dag Brattli, All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * Neither Dag Brattli nor University of Tromsų admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + * + ********************************************************************/ + +#include <net/irda/irda.h> +#include <net/irda/irqueue.h> +#include <net/irda/irlap.h> +#include <net/irda/irlap_comp.h> +#include "../../drivers/net/zlib.h" + +hashbin_t *irlap_compressors = NULL; + +/* + * Function irda_register_compressor (cp) + * + * Register new compressor with the IrLAP + * + */ +int irda_register_compressor( struct compressor *cp) +{ + struct irda_compressor *new; + + DEBUG( 4, __FUNCTION__ "()\n"); + + /* Check if this compressor has been registred before */ + if ( hashbin_find ( irlap_compressors, cp->compress_proto, NULL)) { + DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n"); + return 0; + } + + /* Make new IrDA compressor */ + new = (struct irda_compressor *) + kmalloc( sizeof( struct irda_compressor), GFP_KERNEL); + if (new == NULL) + return 1; + + memset( new, 0, sizeof( struct irda_compressor)); + new->cp = cp; + + /* Insert IrDA compressor into hashbin */ + hashbin_insert( irlap_compressors, (QUEUE *) new, cp->compress_proto, + NULL); + + return 0; +} + +/* + * Function irda_unregister_compressor (cp) + * + * Unregister compressor + * + */ +void irda_unregister_compressor ( struct compressor *cp) +{ + struct irda_compressor *node; + + DEBUG( 4, __FUNCTION__ "()\n"); + + node = hashbin_remove( irlap_compressors, cp->compress_proto, NULL); + if ( !node) { + DEBUG( 0, __FUNCTION__ "(), compressor not found!\n"); + return; + } + + kfree( node); +} + +/* + * Function irda_set_compression (self, proto) + * + * The the compression protocol to be used by this session + * + */ +int irda_set_compression( struct irlap_cb *self, int proto) +{ + struct compressor *cp; + struct irda_compressor *comp; + + __u8 options[CILEN_DEFLATE]; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return -ENODEV;); + ASSERT( self->magic == LAP_MAGIC, return -EBADR;); + + /* Initialize options */ + options[0] = CI_DEFLATE; + options[1] = CILEN_DEFLATE; + options[2] = DEFLATE_METHOD( DEFLATE_METHOD_VAL); + options[3] = DEFLATE_CHK_SEQUENCE; + + comp = hashbin_find( irlap_compressors, proto, NULL); + if ( !comp) { + DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n"); + return -1; + } + + cp = comp->cp; + /* + * Compressor part + */ + if ( self->compressor.state != NULL) + (*self->compressor.cp->comp_free)( self->compressor.state); + self->compressor.state = NULL; + + self->compressor.cp = cp; + self->compressor.state = cp->comp_alloc( options, sizeof( options)); + if ( self->compressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), Failed!\n"); + return -ENOBUFS; + } + + /* + * Decompress part + */ + + if ( self->decompressor.state != NULL) + irda_decomp_free( self->decompressor.state); + self->decompressor.state = NULL; + + self->decompressor.cp = cp; + self->decompressor.state = cp->decomp_alloc( options, sizeof( options)); + if ( self->decompressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), Failed!\n"); + return -ENOBUFS; + } + return 0; +} + +/* + * Function irda_free_compression (self) + * + * + * + */ +void irda_free_compression( struct irlap_cb *self) +{ + DEBUG( 4, __FUNCTION__ "()\n"); + + if ( self->compressor.state) { + irda_comp_free( self->compressor.state); + self->compressor.state = NULL; + } + + if ( self->decompressor.state) { + irda_decomp_free( self->decompressor.state); + self->decompressor.state = NULL; + } +} + +/* + * Function irlap_compress_init (self) + * + * + * + */ +void irlap_compressor_init( struct irlap_cb *self, int compress) +{ + int debug = TRUE; + __u8 options[CILEN_DEFLATE]; + + DEBUG( 0, __FUNCTION__ "()\n"); + + ASSERT( self != NULL, return;); + ASSERT( self->magic == LAP_MAGIC, return;); + + /* Initialize options */ + options[0] = CI_DEFLATE; + options[1] = CILEN_DEFLATE; + options[2] = DEFLATE_METHOD_VAL; + options[3] = DEFLATE_CHK_SEQUENCE; + + /* + * We're agreeing to send compressed packets. + */ + if ( self->compressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), state == NULL\n"); + return; + } + + if ((*self->compressor.cp->comp_init)( self->compressor.state, + options, sizeof( options), + 0, 0, debug)) + { + DEBUG( 0, __FUNCTION__ "(), Compressor running!\n"); + /* ppp->flags |= SC_COMP_RUN; */ + } + + /* + * Initialize decompressor + */ + if ( self->decompressor.state == NULL) { + DEBUG( 0, __FUNCTION__ "(), state == NULL\n"); + return; + } + + if (( self->decompressor.cp->decomp_init)( self->decompressor.state, + options, sizeof( options), + 0, 0, 0, debug)) + { + DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n"); + + /* ppp->flags |= SC_DECOMP_RUN; */ + /* ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); */ + } +} + +/* + * Function irlap_compress_frame (self, skb) + * + * + * + */ +struct sk_buff *irlap_compress_frame( struct irlap_cb *self, + struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int count; + + ASSERT( skb != NULL, return NULL;); + + DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len, + jiffies); + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == LAP_MAGIC, return NULL;); + + /* Check if compressor got initialized */ + if ( self->compressor.state == NULL) { + /* Tell peer that this frame is not compressed */ + skb_push( skb, LAP_COMP_HEADER); + skb->data[0] = IRDA_NORMAL; + + return skb; + } + + /* FIXME: Find out what is the max overhead (not 10) */ + new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10); + if(!new_skb) + return skb; + + skb_reserve( new_skb, LAP_HEADER); + skb_put( new_skb, skb->len+10); + + count = (self->compressor.cp->compress)( self->compressor.state, + skb->data, new_skb->data, + skb->len, new_skb->len); + if( count <= 0) { + DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n"); + dev_kfree_skb( new_skb); + + /* Tell peer that this frame is not compressed */ + skb_push( skb, 1); + skb->data[0] = IRDA_NORMAL; + + return skb; + } + skb_trim( new_skb, count); + + /* Tell peer that this frame is compressed */ + skb_push( new_skb, 1); + new_skb->data[0] = IRDA_COMPRESSED; + + dev_kfree_skb( skb); + + DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", + (int) new_skb->len, jiffies); + + return new_skb; +} + +/* + * Function irlap_decompress_frame (self, skb) + * + * + * + */ +struct sk_buff *irlap_decompress_frame( struct irlap_cb *self, + struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int count; + + DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len); + + ASSERT( self != NULL, return NULL;); + ASSERT( self->magic == LAP_MAGIC, return NULL;); + + ASSERT( self->compressor.state != NULL, return NULL;); + + /* Check if frame is compressed */ + if ( skb->data[0] == IRDA_NORMAL) { + + /* Remove compression header */ + skb_pull( skb, LAP_COMP_HEADER); + + /* + * The frame is not compressed. Pass it to the + * decompression code so it can update its + * dictionary if necessary. + */ + irda_incomp( self->decompressor.state, skb->data, skb->len); + + return skb; + } + + /* Remove compression header */ + skb_pull( skb, LAP_COMP_HEADER); + + new_skb = dev_alloc_skb( 2048); /* FIXME: find the right size */ + if(!new_skb) + return skb; + skb_put( new_skb, 2048); + + count = irda_decompress( self->decompressor.state, skb->data, + skb->len, new_skb->data, new_skb->len); + if ( count <= 0) { + DEBUG( 0, __FUNCTION__ "(), Unable to decompress frame!\n"); + + dev_kfree_skb( new_skb); + return skb; + } + + skb_trim( new_skb, count); + + DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len); + + return new_skb; +} + |