ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/gvpe/src/rohc/decomp.c
Revision: 1.1
Committed: Sun Feb 8 06:02:44 2004 UTC (20 years, 4 months ago) by pcg
Content type: text/plain
Branch: MAIN
CVS Tags: ROHC-IMPORT-2004-02-08
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 pcg 1.1 /*
2     ROHC Project 2003 at Lulea University of Technology, Sweden.
3     Authors: Andreas Vernersson <andver-8@student.luth.se>
4     Daniel Pettersson <danpet-7@student.luth.se>
5     Erik Soderstrom <soderstrom@yahoo.com>
6     Fredrik Lindstrom <frelin-9@student.luth.se>
7     Johan Stenmark <johste-8@student.luth.se>
8     Martin Juhlin <juhlin@users.sourceforge.net>
9     Mikael Larsson <larmik-9@student.luth.se>
10     Robert Maxe <robmax-1@student.luth.se>
11    
12     Copyright (C) 2003 Andreas Vernersson, Daniel Pettersson,
13     Erik Soderström, Fredrik Lindström, Johan Stenmark,
14     Martin Juhlin, Mikael Larsson, Robert Maxe.
15    
16     This program is free software; you can redistribute it and/or modify
17     it under the terms of the GNU General Public License as published by
18     the Free Software Foundation; either version 2 of the License, or
19     (at your option) any later version.
20    
21     This program is distributed in the hope that it will be useful,
22     but WITHOUT ANY WARRANTY; without even the implied warranty of
23     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24     GNU General Public License for more details.
25    
26     You should have received a copy of the GNU General Public License
27     along with this program; if not, write to the Free Software
28     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29     */
30     //----------------------------------------------------------------------------------------------------------------------------------
31     #include "decomp.h"
32     #include "d_ip.h"
33     #include "d_udp.h"
34     #include "d_uncompressed.h"
35     #include "d_udp_lite.h"
36     #include "feedback.h"
37     //----------------------------------------------------------------------------------------------------------------------------------
38     extern struct s_profile d_udplite_profile, d_udp_profile, d_ip_profile, d_uncomp_profile;
39     //----------------------------------------------------------------------------------------------------------------------------------
40     static struct s_profile *d_profiles[D_NUM_PROFILES] = {
41     &d_udplite_profile,
42     &d_udp_profile,
43     &d_ip_profile,
44     &d_uncomp_profile
45     };
46     //----------------------------------------------------------------------------------------------------------------------------------
47     static struct s_profile * find_profile(int id);
48     //----------------------------------------------------------------------------------------------------------------------------------
49     // Increases the context array size in sizes of 2^x (max 16384)
50     // Param state: pointer to decompressor
51     // Param highest cid: cid to adapt context array size with
52     //----------------------------------------------------------------------------------------------------------------------------------
53     void context_array_increase(struct sd_rohc * state, int highestcid)
54     {
55     struct sd_context ** pnew;
56     int calcsize, i;
57    
58     for(i=4; i<15; i++) { // calculate new size of array
59     calcsize = 1<<i;
60     if(highestcid < calcsize)
61     break;
62     }
63     pnew = (struct sd_context**)kmalloc(sizeof(struct sd_context*) * calcsize, GFP_ATOMIC); // allocate new array
64     if(!pnew) {
65     rohc_debugf(0,"[ERROR] context_array_increase(): unable to allocate memory!\n");
66     return;
67     }
68     for(i=0; i<calcsize; i++) // reset all new pointers to NULL
69     pnew[i] = NULL;
70     for(i=0; i<state->context_array_size; i++) // copy all pointers
71     pnew[i] = state->context[i];
72     state->context_array_size = calcsize;
73     kfree(state->context);
74     state->context = pnew;
75     }
76     //----------------------------------------------------------------------------------------------------------------------------------
77     // Decreases the context array size in sizes of 2^x (min 16)
78     // Param state: pointer to decompressor
79     //----------------------------------------------------------------------------------------------------------------------------------
80     void context_array_decrease(struct sd_rohc * state)
81     {
82     struct sd_context ** pnew;
83     int highestcid=0, calcsize, i;
84    
85     for(i=state->context_array_size-1; i>=0; i--) // search for the highest cid (from the end and backwards)
86     if(state->context[i]) {
87     highestcid = i;
88     break;
89     }
90     for(i=4; i<15; i++) { // calculate new size of array
91     calcsize = 1<<i;
92     if(highestcid < calcsize)
93     break;
94     }
95     pnew = (struct sd_context **)kmalloc(sizeof(struct sd_context*) * calcsize, GFP_ATOMIC); // allocate new array
96     if(!pnew) {
97     rohc_debugf(0,"[ERROR] context_array_decrease(): unable to allocate memory!\n");
98     return;
99     }
100     for(i=0; i<calcsize; i++) // reset all new pointers to NULL
101     pnew[i] = NULL;
102     for(i=0; i<=highestcid; i++) // copy all pointers
103     pnew[i] = state->context[i];
104    
105     state->context_array_size = calcsize;
106     kfree(state->context);
107     state->context = pnew;
108     }
109     //----------------------------------------------------------------------------------------------------------------------------------
110     // Finds a specific context
111     // Param state: pointer to decompressor
112     // Param cid: context-id to find in array
113     // Return: pointer to context if found, else NULL
114     //----------------------------------------------------------------------------------------------------------------------------------
115     struct sd_context * find_context(struct sd_rohc * state, int cid)
116     {
117     if(cid < state->context_array_size) // cid must not be equal or larger than the context array size
118     return(state->context[cid]);
119    
120     return(NULL);
121     }
122     //----------------------------------------------------------------------------------------------------------------------------------
123     // Create and allocate a new context with profile specific data
124     // Param state: pointer to decompressor
125     // Param with_cid: context-id (not used for now)
126     // Param profile: profile to be assigned with context
127     // Return: pointer to new context if allocatable, else NULL
128     //----------------------------------------------------------------------------------------------------------------------------------
129     struct sd_context * context_create(struct sd_rohc * state, int with_cid, struct s_profile * profile)
130     {
131     struct sd_context * pnew = (struct sd_context*)kmalloc(sizeof(struct sd_context), GFP_ATOMIC);
132     if(!pnew) {
133     rohc_debugf(0,"[ERROR] context_create(): unable to allocate memory!\n");
134     return(NULL);
135     }
136     pnew->profile = profile;
137     pnew->mode = ROHC_U_MODE;
138     pnew->state = ROHC_NO_CONTEXT;
139     pnew->data = profile->allocate_decode_data();
140     if(!pnew->data) {
141     kfree(pnew);
142     return(NULL);
143     }
144     pnew->curval = 0;
145    
146     pnew->num_recv_packets = 0;
147     pnew->total_uncompressed_size = 0;
148     pnew->total_compressed_size = 0;
149     pnew->header_uncompressed_size = 0;
150     pnew->header_compressed_size = 0;
151     pnew->num_recv_ir = 0;
152     pnew->num_recv_ir_dyn = 0;
153     pnew->num_sent_feedbacks = 0;
154     pnew->num_decomp_failures = 0;
155     pnew->num_decomp_repairs = 0;
156    
157     pnew->first_used = get_milliseconds();
158     pnew->latest_used = get_milliseconds();
159    
160     pnew->total_16_uncompressed = c_create_wlsb(32, 16, 0); // create a window with 16 entries..
161     pnew->total_16_compressed = c_create_wlsb(32, 16, 0);
162     pnew->header_16_uncompressed = c_create_wlsb(32, 16, 0);
163     pnew->header_16_compressed = c_create_wlsb(32, 16, 0);
164    
165     return(pnew);
166     }
167     //----------------------------------------------------------------------------------------------------------------------------------
168     // Free a context and the profile specific data within
169     // Param context: context to free
170     //----------------------------------------------------------------------------------------------------------------------------------
171     void context_free(struct sd_context * context)
172     {
173     if(!context)
174     return;
175    
176     context->profile->free_decode_data(context->data);
177    
178     c_destroy_wlsb(context->total_16_uncompressed);
179     c_destroy_wlsb(context->total_16_compressed);
180     c_destroy_wlsb(context->header_16_uncompressed);
181     c_destroy_wlsb(context->header_16_compressed);
182    
183     kfree(context);
184     }
185     //----------------------------------------------------------------------------------------------------------------------------------
186     // Create and allocate a ROHC-decompressor
187     // Param compressor: pointer to ROHC-compressor
188     // Return: pointer to the newly allocated decompressor
189     //----------------------------------------------------------------------------------------------------------------------------------
190     struct sd_rohc * rohc_alloc_decompressor(struct sc_rohc * compressor)
191     {
192     struct s_medium medium = {ROHC_SMALL_CID, 15 }; //, 3};
193     struct sd_rohc * pnew = (struct sd_rohc *)kmalloc(sizeof(struct sd_rohc), GFP_ATOMIC);
194     if(!pnew) {
195     rohc_debugf(0,"[ERROR] rohc_alloc_decompressor(): unable to allocate memory!\n");
196     return(NULL);
197     }
198     pnew->medium = (struct s_medium*)kmalloc(sizeof(struct s_medium), GFP_ATOMIC);
199     if (!pnew->medium) {
200     rohc_debugf(0,"[ERROR] rohc_alloc_decompressor(): unable to allocate memory (2)!\n");
201     kfree(pnew);
202     return(NULL);
203     }
204     memcpy(pnew->medium, &medium, sizeof(struct s_medium));
205    
206     pnew->compressor = compressor;
207    
208     pnew->context_array_size = 0; // must be zero
209     pnew->context = NULL; // must be NULL
210     context_array_increase(pnew, 0); // initialize array of size 16
211    
212     pnew->maxval = 300;
213     pnew->errval = 100;
214     pnew->okval = 12;
215     pnew->curval = 0;
216    
217     clear_statistics(pnew);
218    
219     return(pnew);
220     }
221     //----------------------------------------------------------------------------------------------------------------------------------
222     // Free and deallocate a ROHC-decompressor
223     // Param state: pointer to the ROHC-decompressor to free
224     //----------------------------------------------------------------------------------------------------------------------------------
225     void rohc_free_decompressor(struct sd_rohc * state)
226     {
227     int i;
228    
229     for(i=0; i<state->context_array_size; i++)
230     if(state->context[i])
231     context_free(state->context[i]);
232     kfree(state->context);
233     kfree(state->medium);
234     kfree(state);
235     }
236     //----------------------------------------------------------------------------------------------------------------------------------
237     // Main function for decompressing a ROHC-packet
238     // Param state: pointer to decompressor
239     // Param ibuf: pointer to incoming packet
240     // Param isize: size of incoming packet
241     // Param obuf: pointer to output buffer
242     // Param osize: size of output buffer
243     // Return: size of decompressed packet
244     //TODO: kolla upp s�ingen annan anropar d_decode_header DIREKT, anropen m�te ske till denna funktion, annars funkar inte statistik och feedback!!
245     //----------------------------------------------------------------------------------------------------------------------------------
246     int rohc_decompress(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize)
247     {
248     int ret;
249     struct sd_decode_data ddata = { -1, 0, 0, NULL }; // { cid, addcidUsed, largecidUsed, sd_context * active }
250    
251     state->statistics.packets_received++;
252     ret = d_decode_header(state, ibuf, isize, obuf, osize, &ddata);
253     if(ddata.active == NULL && (ret == ROHC_ERROR_PACKAGE_FAILED || ret == ROHC_ERROR || ret == ROHC_ERROR_CRC))
254     ret = ROHC_ERROR_NO_CONTEXT;
255    
256     if (ddata.active) {
257     ddata.active->num_recv_packets ++;
258     rohc_debugf(2,"State in decomp %d\n",ddata.active->state );
259     }
260    
261     if (ret >= 0) {
262     if (!ddata.active) {
263     rohc_debugf(1, "decompress: ddata.active == null when ret >=0!\n");
264     } else {
265     struct sd_context *c = ddata.active;
266     c->total_uncompressed_size += ret;
267     c->total_compressed_size += isize;
268    
269     if (state->compressor) {
270     state->compressor->num_packets ++;
271     state->compressor->total_uncompressed_size += ret;
272     state->compressor->total_compressed_size += isize;
273     }
274    
275     c_add_wlsb(c->total_16_uncompressed, 0, 0, ret);
276     c_add_wlsb(c->total_16_compressed, 0,0, isize);
277     }
278     } else if (ddata.active) {
279     ddata.active->num_decomp_failures ++;
280     }
281    
282     //return ret;
283    
284     switch(ret)
285     {
286     case ROHC_ERROR_PACKAGE_FAILED:
287     case ROHC_ERROR:
288     state->statistics.packets_failed_package++;
289     ddata.active->curval += state->errval;
290     if(ddata.active->curval >= state->maxval) {
291     ddata.active->curval = 0;
292     d_operation_mode_feedback(state, ROHC_ERROR_PACKAGE_FAILED, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
293     }
294     break;
295    
296     case ROHC_ERROR_NO_CONTEXT:
297     state->statistics.packets_failed_no_context++;
298     state->curval += state->errval;
299     if(state->curval >= state->maxval) {
300     state->curval = 0;
301     d_operation_mode_feedback(state, ROHC_ERROR_NO_CONTEXT, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ROHC_O_MODE, NULL);
302     }
303     break;
304    
305     case ROHC_FEEDBACK_ONLY:
306     state->statistics.packets_feedback++;
307     break;
308    
309     case ROHC_ERROR_CRC:
310     state->statistics.packets_failed_crc++;
311     ddata.active->curval += state->errval;
312     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
313     rohc_debugf(2,"feedback max %d\n", state->maxval);
314     if(ddata.active->curval >= state->maxval) {
315     ddata.active->curval = 0;
316     d_operation_mode_feedback(state, ROHC_ERROR_CRC, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
317     }
318     break;
319    
320     default: // ROHC_OK_NO_DATA, ROHC_OK
321     state->curval -= state->okval; // framework (S-NACK)
322     ddata.active->curval -= state->okval; // context (NACK)
323     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
324     if(state->curval < 0)
325     state->curval = 0;
326    
327     if(ddata.active->curval < 0)
328     ddata.active->curval = 0;
329    
330     rohc_debugf(2,"feedback curr %d\n", ddata.active->curval);
331     if(ddata.active->mode == ROHC_U_MODE) {
332     ddata.active->mode = ROHC_O_MODE; // switch active context to o-mode
333     d_operation_mode_feedback(state, ROHC_OK, ddata.cid, ddata.addcidUsed, ddata.largecidUsed, ddata.active->mode, ddata.active);
334     }
335     break;
336     }
337     return(ret);
338     }
339     //----------------------------------------------------------------------------------------------------------------------------------
340     // To decompress both large and small cid package
341     //----------------------------------------------------------------------------------------------------------------------------------
342     int rohc_decompress_both(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize, int large)
343     {
344     state->medium->cid_type = large ? ROHC_LARGE_CID : ROHC_SMALL_CID;
345    
346     return rohc_decompress(state, ibuf, isize, obuf, osize);
347     }
348     //----------------------------------------------------------------------------------------------------------------------------------
349     // Decode feedback and context-id if it exist
350     // Param state: pointer to decompressor
351     // Param walk: pointer to incoming packet
352     // Param isize: size of incoming packet
353     // Return: context-id if found, else rohc_feedback_only
354     //----------------------------------------------------------------------------------------------------------------------------------
355     int d_decode_feedback_first(struct sd_rohc * state, unsigned char ** walk, const int isize)
356     {
357     int cid = 0, i, fbloop = 1;
358     unsigned char * startpos = *walk;
359    
360     for(i=0; i<isize; i++) // remove all padded octets
361     if(d_is_paddning(*walk))
362     (*walk)++;
363     else
364     break;
365     while(fbloop) {
366     fbloop = 0;
367     if(d_is_add_cid(*walk)) { // if addcid - extract value
368     cid = d_decode_add_cid(*walk);
369     (*walk)++;
370     }
371     if(d_is_feedback(*walk)) { // is it feedback?
372     if(cid>0)
373     return(ROHC_ERROR_NO_CONTEXT);
374     else
375     *walk += d_decode_feedback(state, *walk);
376     fbloop = 1; // feedback found, keep looping
377     }
378     if((*walk)-startpos >= isize) // end of package
379     return(ROHC_FEEDBACK_ONLY);
380     }
381     return(cid);
382     }
383     //----------------------------------------------------------------------------------------------------------------------------------
384     // Main function for decompressing a ROHC-packet.
385     // Param state: pointer to decompressor
386     // Param ibuf: pointer to incoming packet
387     // Param isize: size of incoming packet
388     // Param obuf: pointer to output buffer
389     // Param osize: size of output buffer
390     // Param ddata: struct that holds important information to pass between several functions
391     // Return: size of decompressed packet
392     //----------------------------------------------------------------------------------------------------------------------------------
393     int d_decode_header(struct sd_rohc * state, unsigned char * ibuf, int isize, unsigned char * obuf, int osize, struct sd_decode_data * ddata)
394     {
395     int largecid=0, size, irdynvar=0, casenew=0;
396    
397     struct s_profile * profile;
398     unsigned char * walk = ibuf;
399    
400     if(isize < 2)
401     return(ROHC_ERROR_NO_CONTEXT);
402     ddata->cid = d_decode_feedback_first(state, &walk, isize);
403     if(ddata->cid == ROHC_FEEDBACK_ONLY || ddata->cid == ROHC_ERROR_NO_CONTEXT)
404     return(ddata->cid);
405    
406     if(ddata->cid > 0 && state->medium->cid_type == ROHC_SMALL_CID)
407     ddata->addcidUsed=1;
408    
409     if(!ddata->addcidUsed && state->medium->cid_type == ROHC_LARGE_CID) { // check if large cids are used
410     largecid = d_sdvalue_size(walk+1);
411     if(largecid >0 && largecid < 3) {
412     ddata->cid = d_sdvalue_decode(walk+1);
413     ddata->largecidUsed=1;
414     } else
415     return(ROHC_ERROR_NO_CONTEXT);
416     }
417    
418     if(d_is_ir(walk)) {
419     profile = find_profile(walk[largecid+1]);
420    
421     if(!rohc_ir_packet_crc_ok(walk, largecid, ddata->addcidUsed, profile))
422     return(ROHC_ERROR_CRC);
423    
424     if(ddata->cid >= state->context_array_size)
425     context_array_increase(state, ddata->cid);
426    
427     if(state->context[ddata->cid] && state->context[ddata->cid]->profile == profile) {
428     ddata->active = state->context[ddata->cid];
429     state->context[ddata->cid] = NULL;
430     } else {
431     casenew=1;
432     ddata->active = context_create(state, ddata->cid, profile);
433     if(!ddata->active)
434     return(ROHC_ERROR_NO_CONTEXT);
435     }
436    
437     ddata->active->num_recv_ir ++;
438     size = ddata->active->profile->decode_ir(state, ddata->active, walk+largecid+3, (isize-(walk-ibuf))-3-largecid, GET_BIT_0(walk), obuf);
439     if(size>0) {
440     context_free(state->context[ddata->cid]);
441     state->context[ddata->cid] = ddata->active;
442     return(size);
443     }
444     if(casenew)
445     context_free(ddata->active);
446     else
447     state->context[ddata->cid] = ddata->active;
448    
449     return(size);
450     } else {
451     ddata->active = find_context(state, ddata->cid); // find context
452     if(ddata->active && ddata->active->profile) { // context is valid
453     ddata->active->latest_used = get_milliseconds();
454     if(d_is_irdyn(walk)) {
455     ddata->active->num_recv_ir_dyn ++;
456     profile = find_profile(walk[largecid+1]);
457     if(profile != ddata->active->profile) { // if IR-DYN changes profile, make comp. transit to NO_CONTEXT-state
458     state->curval = state->maxval;
459     rohc_debugf(2,"IR-DYN changed profile, sending S-NACK.\n");
460     return(ROHC_ERROR_NO_CONTEXT);
461     }
462     if(!rohc_ir_dyn_packet_crc_ok(walk, largecid, ddata->addcidUsed, profile, ddata->active))
463     return(ROHC_ERROR_CRC);
464     irdynvar += 2;
465     }
466     return(ddata->active->profile->decode(state, ddata->active, walk, (isize-(walk-ibuf)), (ddata->largecidUsed ? (1+largecid+irdynvar) : 1+irdynvar), obuf));
467     } else
468     return(ROHC_ERROR_NO_CONTEXT);
469     }
470     return(ROHC_ERROR_NO_CONTEXT);
471     }
472     //----------------------------------------------------------------------------------------------------------------------------------
473     // Decode the Feedback
474     // Param state: pointer to decompressor
475     // Param ibuf: pointer to incoming packet
476     // Return: feedback size including feedback head
477     //----------------------------------------------------------------------------------------------------------------------------------
478     int d_decode_feedback(struct sd_rohc * state, unsigned char * ibuf)
479     {
480     int feedbacksize, head;
481     feedbacksize = d_feedback_size(ibuf); // extract the size of the feedback
482     head = d_feedback_headersize(ibuf); // point to feedback data
483     ibuf += head;
484     #ifdef USER_SPACE
485     feedbackRedir(ibuf, feedbacksize); // if user space application is running, send feedback to it..
486     #else
487     //passFeedback(ibuf, feedbacksize); // ..else pass it on to the compressor
488     if (state->compressor)
489     c_deliver_feedback(state->compressor, ibuf, feedbacksize);
490     #endif
491    
492     return(feedbacksize + head);
493     }
494     //----------------------------------------------------------------------------------------------------------------------------------
495     // Find profile with a certain id
496     // Param id: profile id to find
497     // Return: pointer to the matching profile
498     //----------------------------------------------------------------------------------------------------------------------------------
499     struct s_profile * find_profile(int id)
500     {
501     if(id==0)
502     return uncompressed_profile_create();
503     else if(id==2)
504     return udp_profile_create();
505     else if(id==4)
506     return iponly_profile_create();
507     else if(id==8)
508     return udp_lite_profile_create();
509     else
510     return uncompressed_profile_create();
511     }
512     //----------------------------------------------------------------------------------------------------------------------------------
513     // CRC check on IR-packets
514     // Param walk: pointer to incoming packet
515     // Param largecid: largecid value
516     // Param addcidUsed: value of addcidUsed, if 1 then addcid is used, else 0
517     // Param profile: pointer to profile of packet
518     // Return: 1 if CRC is OK, else 0
519     //----------------------------------------------------------------------------------------------------------------------------------
520     int rohc_ir_packet_crc_ok(unsigned char * walk, const int largecid, const int addcidUsed, const struct s_profile * profile)
521     {
522     int realcrc, crc;
523    
524     realcrc = walk[largecid+2];
525     walk[largecid+2] = 0;
526     if(profile->id==0)
527     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_size(walk, largecid+1)+2+largecid+addcidUsed);
528     else
529     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_size(walk, largecid+1)+3+largecid+addcidUsed);
530     walk[largecid+2] = realcrc;
531     if(crc != realcrc) {
532     rohc_debugf(0,"ROHC Decompress IR: CRC FAILED! SKA: %i, �: %i\n", realcrc, crc);
533     return(0);
534     }
535     rohc_debugf(2,"ROHC Decompress IR: CRC OK!\n");
536    
537     return(1);
538     }
539     //----------------------------------------------------------------------------------------------------------------------------------
540     // CRC check on IR-DYN packets
541     // Param walk: pointer to incoming packet
542     // Param largecid: largecid value'
543     // Param addcidUsed: value of addcidUsed'
544     // Param profile: pointer to profile of packet
545     // Return: 1 if CRC is OK, else 0
546     //----------------------------------------------------------------------------------------------------------------------------------
547     int rohc_ir_dyn_packet_crc_ok(unsigned char * walk, const int largecid, const int addcidUsed, const struct s_profile * profile, struct sd_context * context)
548     {
549     int realcrc, crc;
550    
551     realcrc = walk[largecid+2];
552     walk[largecid+2] = 0;
553     crc = crc_calculate(CRC_TYPE_8, walk-addcidUsed, profile->detect_ir_dyn_size(walk, context)+3+largecid+addcidUsed);
554     walk[largecid+2] = realcrc;
555     if(crc != realcrc) {
556     rohc_debugf(0,"ROHC Decompress IR_DYN: CRC FAILED! SKA: %i, �: %i\n", realcrc, crc);
557     return(0);
558     }
559     rohc_debugf(2,"ROHC Decompress IR_DYN: CRC OK!\n");
560    
561     return(1);
562     }
563     //----------------------------------------------------------------------------------------------------------------------------------
564     // Send Feedback depending on Mode: Unidirectional, Optimistic or Reliable Mode
565     // Param state: pointer to decompressor
566     // Param rohc_status: type of feedback to send; 0 = OK (ack), -1 = ContextInvalid (S-nack), -2 = PackageFailed (Nack)
567     // Param cid: context-id value
568     // Param addcidUsed: ==1 if addcid is used
569     // Param largecidUsed: ==1 if largecid is used
570     // Param mode: mode that ROHC operates in; U-, O- or R-MODE
571     // Param ctxt: active/current context
572     //----------------------------------------------------------------------------------------------------------------------------------
573     void d_operation_mode_feedback(struct sd_rohc * state, int rohc_status, int cid, int addcidUsed, int largecidUsed, int mode, struct sd_context * ctxt)
574     {
575     struct sd_feedback sfeedback;
576     char * feedback;
577     int feedbacksize;
578    
579     switch(mode)
580     {
581     case ROHC_U_MODE:
582     // no feedback needed
583     //break;
584     case ROHC_O_MODE:
585     switch(rohc_status)
586     {
587     case ROHC_OK:
588     f_feedback2(ACKTYPE_ACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
589     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
590     if(!feedback) {
591     rohc_debugf(0,"Feedback: ACK FAILED!\n");
592     return;
593     }
594     ctxt->num_sent_feedbacks++;
595     #ifdef USER_SPACE
596     rohc_debugf(2,"Feedback send to testapp\n");
597     feedbackRedir_piggy(feedback, feedbacksize);
598     #else
599     if(state->compressor)
600     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
601     #endif
602     kfree(feedback);
603     break;
604     case ROHC_ERROR_NO_CONTEXT:
605     f_feedback2(ACKTYPE_STATIC_NACK, ROHC_O_MODE, 0, &sfeedback);
606     f_add_option(&sfeedback, OPT_TYPE_SN_NOT_VALID, NULL);
607     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, NO_CRC, &feedbacksize);
608     if(!feedback) {
609     rohc_debugf(0,"Feedback: ACK FAILED!\n");
610     return;
611     }
612     //ctxt->num_sent_feedbacks++;
613     #ifdef USER_SPACE
614     rohc_debugf(2,"Feedback send to testapp\n");
615     feedbackRedir_piggy(feedback, feedbacksize);
616     #else
617     if(state->compressor)
618     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
619     #endif
620     kfree(feedback);
621     break;
622     case ROHC_ERROR_PACKAGE_FAILED:
623     case ROHC_ERROR_CRC:
624     ctxt->num_sent_feedbacks++;
625     switch(ctxt->state)
626     {
627     case ROHC_NO_CONTEXT:
628     rohc_debugf(2,"No context\n");
629     f_feedback2(ACKTYPE_STATIC_NACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
630     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
631     if(!feedback) {
632     rohc_debugf(0,"Feedback: S-NACK (PF/CRC) FAILED!\n");
633     return;
634     }
635     #ifdef USER_SPACE
636     rohc_debugf(2,"Feedback send to testapp\n");
637     feedbackRedir_piggy(feedback, feedbacksize);
638     #else
639     if(state->compressor)
640     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
641     #endif
642     kfree(feedback);
643     break;
644     case ROHC_STATIC_CONTEXT:
645     case ROHC_FULL_CONTEXT:
646    
647     f_feedback2(ACKTYPE_NACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
648     feedback = f_wrap_feedback(&sfeedback, cid, largecidUsed, WITH_CRC, &feedbacksize);
649     if(!feedback) {
650     rohc_debugf(0,"Feedback: S-NACK (NC/SC) FAILED!\n");
651     return;
652     }
653     #ifdef USER_SPACE
654     rohc_debugf(2,"Feedback send to testapp\n");
655     feedbackRedir_piggy(feedback, feedbacksize);
656     #else
657     if(state->compressor)
658     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
659     #endif
660     if(ctxt->state == ROHC_STATIC_CONTEXT)
661     ctxt->state = ROHC_NO_CONTEXT;
662     if(ctxt->state == ROHC_FULL_CONTEXT)
663     ctxt->state = ROHC_STATIC_CONTEXT;
664     kfree(feedback);
665     break;
666     default:
667     break;
668     }
669     break;
670     }
671     break;
672     case ROHC_R_MODE:
673     // send feedback (not supported for now)
674     break;
675     }
676     }
677     //----------------------------------------------------------------------------------------------------------------------------------
678     // Clear all the statistics
679     // Param state: pointer to decompressor
680     //----------------------------------------------------------------------------------------------------------------------------------
681     void clear_statistics(struct sd_rohc * state)
682     {
683     state->statistics.packets_received = 0;
684     state->statistics.packets_failed_crc = 0;
685     state->statistics.packets_failed_no_context = 0;
686     state->statistics.packets_failed_package = 0;
687     state->statistics.packets_feedback = 0;
688     }
689    
690     //----------------------------------------------------------------------------------------------------------------------------------
691     // Store decompression statistics for a decompressor to the buffer
692     // Param decomp: pointer to the decompressor
693     // Param buffer:
694     //----------------------------------------------------------------------------------------------------------------------------------
695     /* Store decompression statistics for a decompressor to the buffer */
696     int rohc_d_statistics(struct sd_rohc *decomp, char *buffer)
697     {
698     struct s_profile *p;
699     int i;
700    
701     // Decompressor profiles
702     for (i=0; i<D_NUM_PROFILES; i++) {
703     p = d_profiles[i];
704    
705     sprintf(buffer, "%s\n%s\n", buffer, "---Profile");
706     sprintf(buffer, "%sPROFILE NO:%d\n", buffer, p->id);
707     sprintf(buffer, "%sACTIVE:%s\n", buffer, "YES");
708     sprintf(buffer, "%sVERSION NO:%s\n", buffer, p->version);
709     sprintf(buffer, "%sPROFILE TYPE:%s\n", buffer, p->description);
710    
711     }
712    
713     return strlen(buffer);
714     }
715    
716     //----------------------------------------------------------------------------------------------------------------------------------
717     // Decompressor Contexts
718     // Param decomp: pointer to the decompressor
719     // Param index:
720     // Param buffer:
721     //----------------------------------------------------------------------------------------------------------------------------------
722     int rohc_d_context(struct sd_rohc *decomp, int index, char *buffer) {
723     char *modes[4]= {"error", "U-mode", "O-mode", "R-mode"};
724     char *states[4] = {"error", "NC", "SC", "FC"};
725     char *save;
726     struct sd_context *c;
727     int v;
728    
729     if (index >= decomp->context_array_size)
730     return -2;
731    
732     c = decomp->context[index];
733     if (!c || !c->profile)
734     return -1;
735    
736     save = buffer;
737    
738     buffer += strlen(buffer);
739     sprintf(buffer, "\n---Context\n");
740     buffer += strlen(buffer);
741     sprintf(buffer, "CONTEXTTYPE:Decompressor\n");
742     buffer += strlen(buffer);
743     sprintf(buffer, "CID:%d\n", index);
744     buffer += strlen(buffer);
745     sprintf(buffer, "CID_STATE:%s\n", "USED");
746     buffer += strlen(buffer);
747     sprintf(buffer, "STATE:%s\n", states[c->state]);
748     buffer += strlen(buffer);
749     sprintf(buffer, "MODE:%s\n", modes[c->mode]);
750     buffer += strlen(buffer);
751     sprintf(buffer, "PROFILE:%s\n", c->profile->description);
752     buffer += strlen(buffer);
753    
754     if (c->total_uncompressed_size != 0)
755     v = (100*c->total_compressed_size) / c->total_uncompressed_size;
756     else
757     v = 0;
758     if (v < 0) {
759     rohc_debugf(0, "decomp: total_compressed_size=%d total_uncompressed_size=%d\n", c->total_compressed_size, c->total_uncompressed_size);
760     }
761     sprintf(buffer, "TOTALCOMPRATIOALLPACK:%d%%\n", v);
762     buffer += strlen(buffer);
763    
764     if (c->header_uncompressed_size != 0)
765     v = (100*c->header_compressed_size) / c->header_uncompressed_size;
766     else
767     v = 0;
768     sprintf(buffer, "TOTALCOMPRATIOALLPACKHEAD:%d%%\n", v);
769     buffer += strlen(buffer);
770    
771     v = c->total_compressed_size/c->num_recv_packets;
772     sprintf(buffer, "MEANCOMPPACKSIZEALLPACK:%d\n", v);
773     buffer += strlen(buffer);
774    
775     v = c->header_compressed_size/c->num_recv_packets;
776     sprintf(buffer, "MEANHEADSIZEALLCOMPHEAD:%d\n", v);
777     buffer += strlen(buffer);
778    
779     v = c_sum_wlsb(c->total_16_uncompressed);
780     if (v != 0)
781     v = (100 * c_sum_wlsb(c->total_16_compressed)) / v;
782     sprintf(buffer, "COMPRATIOLAST16PACK:%d%%\n", v);
783     buffer += strlen(buffer);
784    
785     v = c_sum_wlsb(c->header_16_uncompressed);
786     if (v != 0)
787     v = (100 * c_sum_wlsb(c->header_16_compressed)) / v;
788     sprintf(buffer, "COMPRATIOLAST16PACKHEAD:%d%%\n", v);
789     buffer += strlen(buffer);
790    
791     v = c_mean_wlsb(c->total_16_compressed);
792     sprintf(buffer, "MEANCOMPPACKSIZELAST16PACK:%d\n", v);
793     buffer += strlen(buffer);
794    
795     v = c_mean_wlsb(c->header_16_compressed);
796     sprintf(buffer, "MEANHEADSIZELAST16COMPHEAD:%d\n", v);
797     buffer += strlen(buffer);
798    
799     sprintf(buffer, "CONTEXTACTIVATIONTIME:%d\n", (get_milliseconds() - c->first_used) / 1000 );
800     buffer += strlen(buffer);
801     sprintf(buffer, "CONTEXTIDLETIME:%d\n", (get_milliseconds() - c->latest_used) / 1000);
802     buffer += strlen(buffer);
803    
804     sprintf(buffer, "NORECVPACKETS:%d\n", c->num_recv_packets);
805     buffer += strlen(buffer);
806     sprintf(buffer, "NORECVIRPACKETS:%d\n", c->num_recv_ir);
807     buffer += strlen(buffer);
808     sprintf(buffer, "NORECVIRDYNPACKETS:%d\n", c->num_recv_ir_dyn);
809     buffer += strlen(buffer);
810     sprintf(buffer, "NOSENTFEEDBACKS:%d\n", c->num_sent_feedbacks);
811     buffer += strlen(buffer);
812     sprintf(buffer, "NODECOMPFAILURES:%d\n", c->num_decomp_failures);
813     buffer += strlen(buffer);
814     sprintf(buffer, "NODECOMPREPAIRS:%d\n", c->num_decomp_repairs);
815     buffer += strlen(buffer);
816    
817     return strlen(save);
818     }
819    
820     //----------------------------------------------------------------------------------------------------------------------------------
821     // Create an ACK-packet telling the compressor to change state
822     // Param state: pointer to decompressor
823     // Param ctxt: pointer to active context
824     //----------------------------------------------------------------------------------------------------------------------------------
825     void d_change_mode_feedback(struct sd_rohc * state, struct sd_context * ctxt)
826     {
827     struct sd_feedback sfeedback;
828     int cid, feedbacksize;
829     char * feedback;
830    
831     for(cid=0; cid < state->context_array_size; cid++)
832     if(ctxt == state->context[cid])
833     break;
834     if(cid >= state->context_array_size)
835     return;
836    
837     f_feedback2(ACKTYPE_ACK, ctxt->mode, ctxt->profile->get_sn(ctxt), &sfeedback);
838     feedback = f_wrap_feedback(&sfeedback, cid, (state->medium->cid_type == ROHC_LARGE_CID ? 1 : 0), WITH_CRC, &feedbacksize);
839    
840     if(!feedback) {
841     rohc_debugf(0,"Feedback [d_change_mode_feedback()]: ACK FAILED!\n");
842     return;
843     }
844     #ifdef USER_SPACE
845     rohc_debugf(2,"Feedback [ACK] sent to testapp.\n");
846     feedbackRedir_piggy(feedback, feedbacksize);
847     #else
848     if(state->compressor)
849     c_piggyback_feedback(state->compressor, feedback, feedbacksize);
850     #endif
851     kfree(feedback);
852     }
853     //----------------------------------------------------------------------------------------------------------------------------------
854     // Update feedback interval with data from the gui
855     // Param state: pointer to the decompressor
856     // Param feedback_maxval: the value from the gui
857     //----------------------------------------------------------------------------------------------------------------------------------
858     void usergui_interactions(struct sd_rohc * state, int feedback_maxval)
859     {
860     state->maxval = feedback_maxval*100;
861     }
862     //----------------------------------------------------------------------------------------------------------------------------------