1 /*********************************************************************
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 */
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,
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
};
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;);
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
;
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
)
87 * These are the maximum supported values as specified on pages
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;
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
,
117 #ifdef CONFIG_IRDA_COMPRESSION
118 int comp_seen
= FALSE
;
126 __u16_host_order word
;
128 ASSERT( qos_tx
!= NULL
, return;);
129 ASSERT( qos_rx
!= NULL
, return;);
130 ASSERT( skb
!= NULL
, return;);
134 while( n
< skb
->len
-2) {
140 * Get the value, since baud_rate may need two bytes, we
141 * Just use word size all the time
146 word
.word
= byte
; /* To make things a little easier */
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
++];
159 DEBUG( 0, __FUNCTION__
"Error\n");
160 word
.word
= byte
= 0;
169 * Stations must agree on baud rate, so calculate
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
;
178 case PI_MAX_TURN_TIME
:
180 * Negotiated independently for each station
182 DEBUG(4, __FUNCTION__
"(), MAX_TURN_TIME: %02x\n",
184 qos_tx
->max_turn_time
.bits
= byte
;
188 * Negotiated independently for each station
190 DEBUG( 4, "DATA_SIZE: %02x\n", byte
);
191 qos_tx
->data_size
.bits
= byte
;
195 * Negotiated independently for each station
197 qos_tx
->window_size
.bits
= byte
;
201 * Negotiated independently for each station
203 DEBUG( 4, "ADD_BOFS: %02x\n", byte
);
204 qos_tx
->additional_bofs
.bits
= byte
;
206 case PI_MIN_TURN_TIME
:
207 DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte
);
208 qos_tx
->min_turn_time
.bits
= byte
;
212 * Stations must agree on link disconnect/threshold
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
;
222 #ifdef CONFIG_IRDA_COMPRESSION
224 final_byte
= byte
& qos_rx
->compression
.bits
;
225 qos_rx
->compression
.bits
= byte
;
226 qos_tx
->compression
.bits
= byte
;
231 DEBUG( 0, __FUNCTION__
"(), Unknown value\n");
235 #ifdef CONFIG_IRDA_COMPRESSION
237 DEBUG( 4, __FUNCTION__
"(), Compression not seen!\n");
238 qos_tx
->compression
.bits
= 0x00;
239 qos_rx
->compression
.bits
= 0x00;
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
);
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
)
276 __u16_host_order word
;
278 ASSERT( qos
!= NULL
, return 0;);
279 ASSERT( frame
!= NULL
, return 0;);
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
;
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 */
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
;
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
;
347 int byte_value( __u8 byte
, int *array
)
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) */
363 /* index = value_index( value, array); */
369 * Function msb_index (word)
371 * Returns index to most significant bit (MSB) in word
374 int msb_index ( __u16 word
)
377 int index
= 15; /* Current MSB */
381 break; /* Found it! */
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
)
399 if ( array
[i
] == value
)
405 * Function index_value (index, array)
407 * Returns value to index in array, easy!
410 int index_value( int index
, int *array
)
415 void irda_qos_bits_to_value( struct qos_info
*qos
)
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
);
445 qos
->compression
.value
= compression
[index
];
447 qos
->compression
.value
= 0;