Import 2.3.4pre3
[davej-history.git] / net / irda / qos.c
blob82f7fc28a70d9a4ad9d4e2d07ae0f8adaa08619f
1 /*********************************************************************
2 *
3 * Filename: qos.c
4 * Version: 0.8
5 * Description: IrLAP QoS negotiation
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Tue Sep 9 00:00:26 1997
9 * Modified at: Mon May 3 21:15:08 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither Dag Brattli nor University of Tromsø admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 ********************************************************************/
26 #include <linux/config.h>
27 #include <asm/byteorder.h>
29 #include <net/irda/irda.h>
30 #include <net/irda/qos.h>
31 #include <net/irda/irlap.h>
32 #ifdef CONFIG_IRDA_COMPRESSION
33 #include <net/irda/irlap_comp.h>
34 #include "../../drivers/net/zlib.h"
36 #define CI_BZIP2 27 /* Random pick */
37 #endif
39 int min_turn_time[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 };
40 int baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 1152000,
41 4000000 };
42 int data_size[] = { 64, 128, 256, 512, 1024, 2048 };
43 int add_bofs[] = { 48, 24, 12, 5, 3, 2, 1, 0 };
44 int max_turn_time[] = { 500, 250, 100, 50 };
45 int link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 };
47 #ifdef CONFIG_IRDA_COMPRESSION
48 int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
49 #endif
51 * Function irda_qos_compute_intersection (qos, new)
53 * Compute the intersection of the old QoS capabilites with new ones
56 void irda_qos_compute_intersection(struct qos_info *qos, struct qos_info *new)
58 ASSERT(qos != NULL, return;);
59 ASSERT(new != NULL, return;);
61 /* Apply */
62 qos->baud_rate.bits &= new->baud_rate.bits;
63 qos->window_size.bits &= new->window_size.bits;
64 qos->min_turn_time.bits &= new->min_turn_time.bits;
65 qos->max_turn_time.bits &= new->max_turn_time.bits;
66 qos->data_size.bits &= new->data_size.bits;
67 qos->link_disc_time.bits &= new->link_disc_time.bits;
68 qos->additional_bofs.bits &= new->additional_bofs.bits;
70 #ifdef CONFIG_IRDA_COMPRESSION
71 qos->compression.bits &= new->compression.bits;
72 #endif
74 irda_qos_bits_to_value(qos);
78 * Function irda_init_max_qos_capabilies (qos)
80 * The purpose of this function is for layers and drivers to be able to
81 * set the maximum QoS possible and then "and in" their own limitations
84 void irda_init_max_qos_capabilies( struct qos_info *qos)
86 /*
87 * These are the maximum supported values as specified on pages
88 * 39-43 in IrLAP
91 /* LSB is first byte, MSB is second byte */
92 qos->baud_rate.bits = 0x01ff;
94 qos->window_size.bits = 0x7f;
95 qos->min_turn_time.bits = 0xff;
96 qos->max_turn_time.bits = 0x0f;
97 qos->data_size.bits = 0x3f;
98 qos->link_disc_time.bits = 0xff;
99 qos->additional_bofs.bits = 0xff;
101 #ifdef CONFIG_IRDA_COMPRESSION
102 qos->compression.bits = 0x03;
103 #endif
107 * Function irlap_negotiate (qos_device, qos_session, skb)
109 * Negotiate QoS values, not really that much negotiation :-)
110 * We just set the QoS capabilities for the peer station
113 void irda_qos_negotiate(struct qos_info *qos_rx, struct qos_info *qos_tx,
114 struct sk_buff *skb)
116 int n=0;
117 #ifdef CONFIG_IRDA_COMPRESSION
118 int comp_seen = FALSE;
119 #endif
120 __u8 length;
121 __u8 *frame;
122 __u8 final_byte;
123 __u8 code;
124 __u8 byte;
125 __u16 final_word;
126 __u16_host_order word;
128 ASSERT( qos_tx != NULL, return;);
129 ASSERT( qos_rx != NULL, return;);
130 ASSERT( skb != NULL, return;);
132 frame = skb->data;
134 while( n < skb->len-2) {
135 code = frame[n++];
136 /* Length */
137 length = frame[n++];
140 * Get the value, since baud_rate may need two bytes, we
141 * Just use word size all the time
143 switch( length) {
144 case 1:
145 byte = frame[n++];
146 word.word = byte; /* To make things a little easier */
147 break;
148 case 2:
149 #ifdef __LITTLE_ENDIAN
150 word.byte[0] = frame[n++];
151 word.byte[1] = frame[n++];
152 #else ifdef __BIG_ENDIAN
153 word.byte[1] = frame[n++];
154 word.byte[0] = frame[n++];
155 #endif
156 byte = 0;
157 break;
158 default:
159 DEBUG( 0, __FUNCTION__ "Error\n");
160 word.word = byte = 0;
161 n += length;
163 break;
166 switch(code) {
167 case PI_BAUD_RATE:
169 * Stations must agree on baud rate, so calculate
170 * intersection
172 DEBUG( 4, "Requested BAUD_RATE: 0x%04x\n", word.word);
173 final_word = word.word & qos_rx->baud_rate.bits;
174 DEBUG( 4, "Final BAUD_RATE: 0x%04x\n", final_word);
175 qos_tx->baud_rate.bits = final_word;
176 qos_rx->baud_rate.bits = final_word;
177 break;
178 case PI_MAX_TURN_TIME:
180 * Negotiated independently for each station
182 DEBUG(4, __FUNCTION__ "(), MAX_TURN_TIME: %02x\n",
183 byte);
184 qos_tx->max_turn_time.bits = byte;
185 break;
186 case PI_DATA_SIZE:
188 * Negotiated independently for each station
190 DEBUG( 4, "DATA_SIZE: %02x\n", byte);
191 qos_tx->data_size.bits = byte;
192 break;
193 case PI_WINDOW_SIZE:
195 * Negotiated independently for each station
197 qos_tx->window_size.bits = byte;
198 break;
199 case PI_ADD_BOFS:
201 * Negotiated independently for each station
203 DEBUG( 4, "ADD_BOFS: %02x\n", byte);
204 qos_tx->additional_bofs.bits = byte;
205 break;
206 case PI_MIN_TURN_TIME:
207 DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte);
208 qos_tx->min_turn_time.bits = byte;
209 break;
210 case PI_LINK_DISC:
212 * Stations must agree on link disconnect/threshold
213 * time.
215 DEBUG( 4, "LINK_DISC: %02x\n", byte);
217 final_byte = byte & qos_rx->link_disc_time.bits;
218 DEBUG( 4, "Final LINK_DISC: %02x\n", final_byte);
219 qos_tx->link_disc_time.bits = final_byte;
220 qos_rx->link_disc_time.bits = final_byte;
221 break;
222 #ifdef CONFIG_IRDA_COMPRESSION
223 case PI_COMPRESSION:
224 final_byte = byte & qos_rx->compression.bits;
225 qos_rx->compression.bits = byte;
226 qos_tx->compression.bits = byte;
227 comp_seen = TRUE;
228 break;
229 #endif
230 default:
231 DEBUG( 0, __FUNCTION__ "(), Unknown value\n");
232 break;
235 #ifdef CONFIG_IRDA_COMPRESSION
236 if ( !comp_seen) {
237 DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
238 qos_tx->compression.bits = 0x00;
239 qos_rx->compression.bits = 0x00;
241 #endif
242 /* Convert the negotiated bits to values */
243 irda_qos_bits_to_value( qos_tx);
244 irda_qos_bits_to_value( qos_rx);
246 DEBUG( 4, "Setting BAUD_RATE to %d bps.\n",
247 qos_tx->baud_rate.value);
248 DEBUG( 4, "Setting DATA_SIZE to %d bytes\n",
249 qos_tx->data_size.value);
250 DEBUG( 4, "Setting WINDOW_SIZE to %d\n",
251 qos_tx->window_size.value);
252 DEBUG( 4, "Setting XBOFS to %d\n",
253 qos_tx->additional_bofs.value);
254 DEBUG( 4, "Setting MAX_TURN_TIME to %d ms.\n",
255 qos_tx->max_turn_time.value);
256 DEBUG( 4, "Setting MIN_TURN_TIME to %d usecs.\n",
257 qos_tx->min_turn_time.value);
258 DEBUG( 4, "Setting LINK_DISC to %d secs.\n",
259 qos_tx->link_disc_time.value);
260 #ifdef CONFIG_IRDA_COMPRESSION
261 DEBUG( 4, "Setting COMPRESSION to %d\n",
262 qos_tx->compression.value);
263 #endif
268 * Function irlap_insert_negotiation_params (qos, fp)
270 * Insert QoS negotiaion pararameters into frame
273 int irda_insert_qos_negotiation_params(struct qos_info *qos, __u8 *frame)
275 int n;
276 __u16_host_order word;
278 ASSERT( qos != NULL, return 0;);
279 ASSERT( frame != NULL, return 0;);
281 n = 0;
283 /* Set baud rate */
284 if (qos->baud_rate.bits < 256) {
285 frame[n++] = PI_BAUD_RATE;
286 frame[n++] = 0x01; /* length 1 */
287 frame[n++] = qos->baud_rate.bits;
288 } else {
289 frame[n++] = PI_BAUD_RATE;
290 frame[n++] = 0x02; /* length 2 */
293 * qos->baud_rate.bits is in host byte order, so make sure
294 * we transmit it in little endian format
296 word.word = qos->baud_rate.bits;
297 #ifdef __LITTLE_ENDIAN
298 frame[n++] = word.byte[0]; /* LSB */
299 frame[n++] = word.byte[1]; /* MSB */
300 #else ifdef __BIG_ENDIAN
301 frame[n++] = word.byte[1]; /* LSB */
302 frame[n++] = word.byte[0]; /* MSB */
303 #endif
306 /* Set Maximum Turn Around Time */
307 frame[n++] = PI_MAX_TURN_TIME;
308 frame[n++] = 0x01; /* length 1 */
309 frame[n++] = qos->max_turn_time.bits;
311 /* Set data size */
312 frame[n++] = PI_DATA_SIZE;
313 frame[n++] = 0x01; /* length 1 */
314 frame[n++] = qos->data_size.bits;
316 /* Set window size */
317 frame[n++] = PI_WINDOW_SIZE;
318 frame[n++] = 0x01; /* length 1 */
319 frame[n++] = qos->window_size.bits;
321 /* Set additional BOFs */
322 frame[n++] = PI_ADD_BOFS;
323 frame[n++] = 0x01; /* length 1 */
324 frame[n++] = qos->additional_bofs.bits;
326 /* Set minimum turn around time */
327 frame[n++] = PI_MIN_TURN_TIME;
328 frame[n++] = 0x01; /* length 1 */
329 frame[n++] = qos->min_turn_time.bits;
331 /* Set Link Disconnect/Threshold Time */
332 frame[n++] = PI_LINK_DISC;
333 frame[n++] = 0x01; /* length 1 */
334 frame[n++] = qos->link_disc_time.bits;
335 #ifdef CONFIG_IRDA_COMPRESSION
336 /* Set compression bits*/
337 if ( qos->compression.bits) {
338 DEBUG( 4, __FUNCTION__ "(), inserting compresion bits\n");
339 frame[n++] = PI_COMPRESSION;
340 frame[n++] = 0x01; /* length 1 */
341 frame[n++] = qos->compression.bits;
343 #endif
344 return n;
347 int byte_value( __u8 byte, int *array)
349 int index;
351 ASSERT( array != NULL, return -1;);
353 index = msb_index( byte);
354 return index_value( index, array);
358 /* __u8 value_byte( int value, int *array) */
359 /* { */
360 /* int index; */
361 /* __u8 byte; */
363 /* index = value_index( value, array); */
365 /* byte = */
366 /* } */
369 * Function msb_index (word)
371 * Returns index to most significant bit (MSB) in word
374 int msb_index ( __u16 word)
376 __u16 msb = 0x8000;
377 int index = 15; /* Current MSB */
379 while( msb) {
380 if ( word & msb)
381 break; /* Found it! */
382 msb >>=1;
383 index--;
386 return index;
390 * Function value_index (value, array)
392 * Returns the index to the value in the specified array
394 int value_index( int value, int *array)
396 int i;
398 for( i=0;i<8;i++)
399 if ( array[i] == value)
400 break;
401 return i;
405 * Function index_value (index, array)
407 * Returns value to index in array, easy!
410 int index_value( int index, int *array)
412 return array[index];
415 void irda_qos_bits_to_value( struct qos_info *qos)
417 int index;
419 ASSERT( qos != NULL, return;);
421 index = msb_index( qos->baud_rate.bits);
422 qos->baud_rate.value = baud_rates[index];
424 index = msb_index( qos->data_size.bits);
425 qos->data_size.value = data_size[index];
427 index = msb_index( qos->window_size.bits);
428 qos->window_size.value = index+1;
430 index = msb_index( qos->min_turn_time.bits);
431 qos->min_turn_time.value = min_turn_time[index];
433 index = msb_index( qos->max_turn_time.bits);
434 qos->max_turn_time.value = max_turn_time[index];
436 index = msb_index( qos->link_disc_time.bits);
437 qos->link_disc_time.value = link_disc_time[index];
439 index = msb_index( qos->additional_bofs.bits);
440 qos->additional_bofs.value = add_bofs[index];
442 #ifdef CONFIG_IRDA_COMPRESSION
443 index = msb_index( qos->compression.bits);
444 if ( index >= 0)
445 qos->compression.value = compression[index];
446 else
447 qos->compression.value = 0;
448 #endif