1 /*********************************************************************
6 * Description: IrLAP QoS parameter negotiation
7 * Status: Experimental.
8 * Author: Dag Brattli <dagb@cs.uit.no>
9 * Created at: Tue Sep 9 00:00:26 1997
10 * Modified at: Tue Oct 5 11:50:41 1999
11 * Modified by: Dag Brattli <dagb@cs.uit.no>
13 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
14 * All Rights Reserved.
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of
19 * the License, or (at your option) any later version.
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.
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,
31 ********************************************************************/
33 #include <linux/config.h>
34 #include <asm/byteorder.h>
36 #include <net/irda/irda.h>
37 #include <net/irda/parameters.h>
38 #include <net/irda/qos.h>
39 #include <net/irda/irlap.h>
40 #ifdef CONFIG_IRDA_COMPRESSION
41 #include <net/irda/irlap_comp.h>
42 #include "../../drivers/net/zlib.h"
44 #define CI_BZIP2 27 /* Random pick */
47 static int irlap_param_baud_rate(void *instance
, param_t
*param
, int get
);
48 static int irlap_param_link_disconnect(void *instance
, param_t
*parm
, int get
);
49 static int irlap_param_max_turn_time(void *instance
, param_t
*param
, int get
);
50 static int irlap_param_data_size(void *instance
, param_t
*param
, int get
);
51 static int irlap_param_window_size(void *instance
, param_t
*param
, int get
);
52 static int irlap_param_additional_bofs(void *instance
, param_t
*parm
, int get
);
53 static int irlap_param_min_turn_time(void *instance
, param_t
*param
, int get
);
55 __u32 min_turn_time
[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
56 __u32 baud_rates
[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000,
57 1152000, 4000000, 16000000 }; /* bps */
58 __u32 data_size
[] = { 64, 128, 256, 512, 1024, 2048 }; /* bytes */
59 __u32 add_bofs
[] = { 48, 24, 12, 5, 3, 2, 1, 0 }; /* bytes */
60 __u32 max_turn_time
[] = { 500, 250, 100, 50 }; /* ms */
61 __u32 link_disc_time
[] = { 3, 8, 12, 16, 20, 25, 30, 40 }; /* secs */
63 #ifdef CONFIG_IRDA_COMPRESSION
64 __u32 compression
[] = { CI_BZIP2
, CI_DEFLATE
, CI_DEFLATE_DRAFT
};
67 static pi_minor_info_t pi_minor_call_table_type_0
[] = {
69 /* 01 */{ irlap_param_baud_rate
, PV_INTEGER
| PV_LITTLE_ENDIAN
},
76 /* 08 */{ irlap_param_link_disconnect
, PV_INT_8_BITS
}
79 static pi_minor_info_t pi_minor_call_table_type_1
[] = {
82 /* 82 */{ irlap_param_max_turn_time
, PV_INT_8_BITS
},
83 /* 83 */{ irlap_param_data_size
, PV_INT_8_BITS
},
84 /* 84 */{ irlap_param_window_size
, PV_INT_8_BITS
},
85 /* 85 */{ irlap_param_additional_bofs
, PV_INT_8_BITS
},
86 /* 86 */{ irlap_param_min_turn_time
, PV_INT_8_BITS
},
89 static pi_major_info_t pi_major_call_table
[] = {
90 { pi_minor_call_table_type_0
, 9 },
91 { pi_minor_call_table_type_1
, 7 },
94 static pi_param_info_t irlap_param_info
= { pi_major_call_table
, 2, 0x7f, 7 };
97 * Function irda_qos_compute_intersection (qos, new)
99 * Compute the intersection of the old QoS capabilites with new ones
102 void irda_qos_compute_intersection(struct qos_info
*qos
, struct qos_info
*new)
104 ASSERT(qos
!= NULL
, return;);
105 ASSERT(new != NULL
, return;);
108 qos
->baud_rate
.bits
&= new->baud_rate
.bits
;
109 qos
->window_size
.bits
&= new->window_size
.bits
;
110 qos
->min_turn_time
.bits
&= new->min_turn_time
.bits
;
111 qos
->max_turn_time
.bits
&= new->max_turn_time
.bits
;
112 qos
->data_size
.bits
&= new->data_size
.bits
;
113 qos
->link_disc_time
.bits
&= new->link_disc_time
.bits
;
114 qos
->additional_bofs
.bits
&= new->additional_bofs
.bits
;
116 #ifdef CONFIG_IRDA_COMPRESSION
117 qos
->compression
.bits
&= new->compression
.bits
;
120 irda_qos_bits_to_value(qos
);
124 * Function irda_init_max_qos_capabilies (qos)
126 * The purpose of this function is for layers and drivers to be able to
127 * set the maximum QoS possible and then "and in" their own limitations
130 void irda_init_max_qos_capabilies(struct qos_info
*qos
)
133 * These are the maximum supported values as specified on pages
137 /* LSB is first byte, MSB is second byte */
138 qos
->baud_rate
.bits
= 0x01ff;
140 qos
->window_size
.bits
= 0x7f;
141 qos
->min_turn_time
.bits
= 0xff;
142 qos
->max_turn_time
.bits
= 0x0f;
143 qos
->data_size
.bits
= 0x3f;
144 qos
->link_disc_time
.bits
= 0xff;
145 qos
->additional_bofs
.bits
= 0xff;
147 #ifdef CONFIG_IRDA_COMPRESSION
148 qos
->compression
.bits
= 0x03;
153 * Function irlap_negotiate (qos_device, qos_session, skb)
155 * Negotiate QoS values, not really that much negotiation :-)
156 * We just set the QoS capabilities for the peer station
159 int irlap_qos_negotiate(struct irlap_cb
*self
, struct sk_buff
*skb
)
162 #ifdef CONFIG_IRDA_COMPRESSION
163 int comp_seen
= FALSE
;
165 ret
= irda_param_extract_all(self
, skb
->data
, skb
->len
,
168 #ifdef CONFIG_IRDA_COMPRESSION
170 IRDA_DEBUG( 4, __FUNCTION__
"(), Compression not seen!\n");
171 self
->qos_tx
.compression
.bits
= 0x00;
172 self
->qos_rx
.compression
.bits
= 0x00;
176 /* Convert the negotiated bits to values */
177 irda_qos_bits_to_value(&self
->qos_tx
);
178 irda_qos_bits_to_value(&self
->qos_rx
);
180 IRDA_DEBUG(2, "Setting BAUD_RATE to %d bps.\n",
181 self
->qos_tx
.baud_rate
.value
);
182 IRDA_DEBUG(2, "Setting DATA_SIZE to %d bytes\n",
183 self
->qos_tx
.data_size
.value
);
184 IRDA_DEBUG(2, "Setting WINDOW_SIZE to %d\n",
185 self
->qos_tx
.window_size
.value
);
186 IRDA_DEBUG(2, "Setting XBOFS to %d\n",
187 self
->qos_tx
.additional_bofs
.value
);
188 IRDA_DEBUG(2, "Setting MAX_TURN_TIME to %d ms.\n",
189 self
->qos_tx
.max_turn_time
.value
);
190 IRDA_DEBUG(2, "Setting MIN_TURN_TIME to %d usecs.\n",
191 self
->qos_tx
.min_turn_time
.value
);
192 IRDA_DEBUG(2, "Setting LINK_DISC to %d secs.\n",
193 self
->qos_tx
.link_disc_time
.value
);
194 #ifdef CONFIG_IRDA_COMPRESSION
195 IRDA_DEBUG(2, "Setting COMPRESSION to %d\n",
196 self
->qos_tx
.compression
.value
);
202 * Function irlap_insert_negotiation_params (qos, fp)
204 * Insert QoS negotiaion pararameters into frame
207 int irlap_insert_qos_negotiation_params(struct irlap_cb
*self
,
212 /* Insert data rate */
213 ret
= irda_param_insert(self
, PI_BAUD_RATE
, skb
->tail
,
214 skb_tailroom(skb
), &irlap_param_info
);
219 /* Insert max turnaround time */
220 ret
= irda_param_insert(self
, PI_MAX_TURN_TIME
, skb
->tail
,
221 skb_tailroom(skb
), &irlap_param_info
);
226 /* Insert data size */
227 ret
= irda_param_insert(self
, PI_DATA_SIZE
, skb
->tail
,
228 skb_tailroom(skb
), &irlap_param_info
);
233 /* Insert window size */
234 ret
= irda_param_insert(self
, PI_WINDOW_SIZE
, skb
->tail
,
235 skb_tailroom(skb
), &irlap_param_info
);
240 /* Insert additional BOFs */
241 ret
= irda_param_insert(self
, PI_ADD_BOFS
, skb
->tail
,
242 skb_tailroom(skb
), &irlap_param_info
);
247 /* Insert minimum turnaround time */
248 ret
= irda_param_insert(self
, PI_MIN_TURN_TIME
, skb
->tail
,
249 skb_tailroom(skb
), &irlap_param_info
);
254 /* Insert link disconnect/threshold time */
255 ret
= irda_param_insert(self
, PI_LINK_DISC
, skb
->tail
,
256 skb_tailroom(skb
), &irlap_param_info
);
265 * Function irlap_param_baud_rate (instance, param, get)
267 * Negotiate data-rate
270 static int irlap_param_baud_rate(void *instance
, param_t
*param
, int get
)
274 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
276 ASSERT(self
!= NULL
, return -1;);
277 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
280 param
->pv
.i
= self
->qos_rx
.baud_rate
.bits
;
281 IRDA_DEBUG(2, __FUNCTION__
"(), baud rate = 0x%02x\n", param
->pv
.i
);
284 * Stations must agree on baud rate, so calculate
287 IRDA_DEBUG(2, "Requested BAUD_RATE: 0x%04x\n", param
->pv
.s
);
288 final
= param
->pv
.s
& self
->qos_rx
.baud_rate
.bits
;
290 IRDA_DEBUG(2, "Final BAUD_RATE: 0x%04x\n", final
);
291 self
->qos_tx
.baud_rate
.bits
= final
;
292 self
->qos_rx
.baud_rate
.bits
= final
;
299 * Function irlap_param_link_disconnect (instance, param, get)
301 * Negotiate link disconnect/threshold time.
304 static int irlap_param_link_disconnect(void *instance
, param_t
*param
, int get
)
308 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
310 ASSERT(self
!= NULL
, return -1;);
311 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
314 param
->pv
.b
= self
->qos_rx
.link_disc_time
.bits
;
317 * Stations must agree on link disconnect/threshold
320 IRDA_DEBUG(2, "LINK_DISC: %02x\n", param
->pv
.b
);
321 final
= param
->pv
.b
& self
->qos_rx
.link_disc_time
.bits
;
323 IRDA_DEBUG(2, "Final LINK_DISC: %02x\n", final
);
324 self
->qos_tx
.link_disc_time
.bits
= final
;
325 self
->qos_rx
.link_disc_time
.bits
= final
;
331 * Function irlap_param_max_turn_time (instance, param, get)
333 * Negotiate the maximum turnaround time. This is a type 1 parameter and
334 * will be negotiated independently for each station
337 static int irlap_param_max_turn_time(void *instance
, param_t
*param
, int get
)
339 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
341 ASSERT(self
!= NULL
, return -1;);
342 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
345 param
->pv
.b
= self
->qos_rx
.max_turn_time
.bits
;
347 self
->qos_tx
.max_turn_time
.bits
= param
->pv
.b
;
353 * Function irlap_param_data_size (instance, param, get)
355 * Negotiate the data size. This is a type 1 parameter and
356 * will be negotiated independently for each station
359 static int irlap_param_data_size(void *instance
, param_t
*param
, int get
)
361 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
363 ASSERT(self
!= NULL
, return -1;);
364 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
367 param
->pv
.b
= self
->qos_rx
.data_size
.bits
;
369 self
->qos_tx
.data_size
.bits
= param
->pv
.b
;
375 * Function irlap_param_window_size (instance, param, get)
377 * Negotiate the window size. This is a type 1 parameter and
378 * will be negotiated independently for each station
381 static int irlap_param_window_size(void *instance
, param_t
*param
, int get
)
383 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
385 ASSERT(self
!= NULL
, return -1;);
386 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
389 param
->pv
.b
= self
->qos_rx
.window_size
.bits
;
391 self
->qos_tx
.window_size
.bits
= param
->pv
.b
;
397 * Function irlap_param_additional_bofs (instance, param, get)
399 * Negotiate additional BOF characters. This is a type 1 parameter and
400 * will be negotiated independently for each station.
402 static int irlap_param_additional_bofs(void *instance
, param_t
*param
, int get
)
404 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
406 ASSERT(self
!= NULL
, return -1;);
407 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
410 param
->pv
.b
= self
->qos_rx
.additional_bofs
.bits
;
412 self
->qos_tx
.additional_bofs
.bits
= param
->pv
.b
;
418 * Function irlap_param_min_turn_time (instance, param, get)
420 * Negotiate the minimum turn around time. This is a type 1 parameter and
421 * will be negotiated independently for each station
423 static int irlap_param_min_turn_time(void *instance
, param_t
*param
, int get
)
425 struct irlap_cb
*self
= (struct irlap_cb
*) instance
;
427 ASSERT(self
!= NULL
, return -1;);
428 ASSERT(self
->magic
== LAP_MAGIC
, return -1;);
431 param
->pv
.b
= self
->qos_rx
.min_turn_time
.bits
;
433 self
->qos_tx
.min_turn_time
.bits
= param
->pv
.b
;
438 __u32
byte_value(__u8 byte
, __u32
*array
)
442 ASSERT(array
!= NULL
, return -1;);
444 index
= msb_index(byte
);
446 return index_value(index
, array
);
450 * Function msb_index (word)
452 * Returns index to most significant bit (MSB) in word
455 int msb_index (__u16 word
)
458 int index
= 15; /* Current MSB */
462 break; /* Found it! */
471 * Function value_index (value, array)
473 * Returns the index to the value in the specified array
475 int value_index(__u32 value
, __u32
*array
)
480 if (array
[i
] == value
)
486 * Function index_value (index, array)
488 * Returns value to index in array, easy!
491 __u32
index_value(int index
, __u32
*array
)
496 void irda_qos_bits_to_value(struct qos_info
*qos
)
500 ASSERT(qos
!= NULL
, return;);
502 index
= msb_index(qos
->baud_rate
.bits
);
503 qos
->baud_rate
.value
= baud_rates
[index
];
505 index
= msb_index(qos
->data_size
.bits
);
506 qos
->data_size
.value
= data_size
[index
];
508 index
= msb_index(qos
->window_size
.bits
);
509 qos
->window_size
.value
= index
+1;
511 index
= msb_index(qos
->min_turn_time
.bits
);
512 qos
->min_turn_time
.value
= min_turn_time
[index
];
514 index
= msb_index(qos
->max_turn_time
.bits
);
515 qos
->max_turn_time
.value
= max_turn_time
[index
];
517 index
= msb_index(qos
->link_disc_time
.bits
);
518 qos
->link_disc_time
.value
= link_disc_time
[index
];
520 index
= msb_index(qos
->additional_bofs
.bits
);
521 qos
->additional_bofs
.value
= add_bofs
[index
];
523 #ifdef CONFIG_IRDA_COMPRESSION
524 index
= msb_index(qos
->compression
.bits
);
526 qos
->compression
.value
= compression
[index
];
528 qos
->compression
.value
= 0;