Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /********************************************************************* |
2 | * | |
3 | * Filename: irlap.h | |
4 | * Version: 0.8 | |
5 | * Description: An IrDA LAP driver for Linux | |
6 | * Status: Experimental. | |
7 | * Author: Dag Brattli <dagb@cs.uit.no> | |
8 | * Created at: Mon Aug 4 20:40:53 1997 | |
9 | * Modified at: Fri Dec 10 13:21:17 1999 | |
10 | * Modified by: Dag Brattli <dagb@cs.uit.no> | |
11 | * | |
12 | * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, | |
13 | * All Rights Reserved. | |
14 | * Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com> | |
15 | * | |
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. | |
20 | * | |
121e70b6 | 21 | * Neither Dag Brattli nor University of Tromsø admit liability nor |
1da177e4 LT |
22 | * provide warranty for any of this software. This material is |
23 | * provided "AS-IS" and at no charge. | |
24 | * | |
25 | ********************************************************************/ | |
26 | ||
27 | #ifndef IRLAP_H | |
28 | #define IRLAP_H | |
29 | ||
1da177e4 LT |
30 | #include <linux/types.h> |
31 | #include <linux/skbuff.h> | |
32 | #include <linux/netdevice.h> | |
33 | #include <linux/timer.h> | |
34 | ||
35 | #include <net/irda/irqueue.h> /* irda_queue_t */ | |
36 | #include <net/irda/qos.h> /* struct qos_info */ | |
37 | #include <net/irda/discovery.h> /* discovery_t */ | |
38 | #include <net/irda/irlap_event.h> /* IRLAP_STATE, ... */ | |
39 | #include <net/irda/irmod.h> /* struct notify_t */ | |
40 | ||
41 | #define CONFIG_IRDA_DYNAMIC_WINDOW 1 | |
42 | ||
43 | #define LAP_RELIABLE 1 | |
44 | #define LAP_UNRELIABLE 0 | |
45 | ||
46 | #define LAP_ADDR_HEADER 1 /* IrLAP Address Header */ | |
47 | #define LAP_CTRL_HEADER 1 /* IrLAP Control Header */ | |
48 | ||
49 | /* May be different when we get VFIR */ | |
50 | #define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER) | |
51 | ||
d93077fb SO |
52 | /* Each IrDA device gets a random 32 bits IRLAP device address */ |
53 | #define LAP_ALEN 4 | |
54 | ||
1da177e4 LT |
55 | #define BROADCAST 0xffffffff /* Broadcast device address */ |
56 | #define CBROADCAST 0xfe /* Connection broadcast address */ | |
57 | #define XID_FORMAT 0x01 /* Discovery XID format */ | |
58 | ||
59 | /* Nobody seems to use this constant. */ | |
60 | #define LAP_WINDOW_SIZE 8 | |
61 | /* We keep the LAP queue very small to minimise the amount of buffering. | |
62 | * this improve latency and reduce resource consumption. | |
63 | * This work only because we have synchronous refilling of IrLAP through | |
64 | * the flow control mechanism (via scheduler and IrTTP). | |
65 | * 2 buffers is the minimum we can work with, one that we send while polling | |
66 | * IrTTP, and another to know that we should not send the pf bit. | |
67 | * Jean II */ | |
68 | #define LAP_HIGH_THRESHOLD 2 | |
69 | /* Some rare non TTP clients don't implement flow control, and | |
70 | * so don't comply with the above limit (and neither with this one). | |
71 | * For IAP and management, it doesn't matter, because they never transmit much. | |
72 | *.For IrLPT, this should be fixed. | |
73 | * - Jean II */ | |
74 | #define LAP_MAX_QUEUE 10 | |
75 | /* Please note that all IrDA management frames (LMP/TTP conn req/disc and | |
76 | * IAS queries) fall in the second category and are sent to LAP even if TTP | |
77 | * is stopped. This means that those frames will wait only a maximum of | |
78 | * two (2) data frames before beeing sent on the "wire", which speed up | |
79 | * new socket setup when the link is saturated. | |
80 | * Same story for two sockets competing for the medium : if one saturates | |
81 | * the LAP, when the other want to transmit it only has to wait for | |
82 | * maximum three (3) packets (2 + one scheduling), which improve performance | |
83 | * of delay sensitive applications. | |
84 | * Jean II */ | |
85 | ||
86 | #define NR_EXPECTED 1 | |
87 | #define NR_UNEXPECTED 0 | |
88 | #define NR_INVALID -1 | |
89 | ||
90 | #define NS_EXPECTED 1 | |
91 | #define NS_UNEXPECTED 0 | |
92 | #define NS_INVALID -1 | |
93 | ||
94 | /* | |
95 | * Meta information passed within the IrLAP state machine | |
96 | */ | |
97 | struct irlap_info { | |
98 | __u8 caddr; /* Connection address */ | |
99 | __u8 control; /* Frame type */ | |
100 | __u8 cmd; | |
101 | ||
102 | __u32 saddr; | |
103 | __u32 daddr; | |
104 | ||
105 | int pf; /* Poll/final bit set */ | |
106 | ||
107 | __u8 nr; /* Sequence number of next frame expected */ | |
108 | __u8 ns; /* Sequence number of frame sent */ | |
109 | ||
110 | int S; /* Number of slots */ | |
111 | int slot; /* Random chosen slot */ | |
112 | int s; /* Current slot */ | |
113 | ||
114 | discovery_t *discovery; /* Discovery information */ | |
115 | }; | |
116 | ||
117 | /* Main structure of IrLAP */ | |
118 | struct irlap_cb { | |
119 | irda_queue_t q; /* Must be first */ | |
120 | magic_t magic; | |
121 | ||
122 | /* Device we are attached to */ | |
123 | struct net_device *netdev; | |
124 | char hw_name[2*IFNAMSIZ + 1]; | |
125 | ||
126 | /* Connection state */ | |
127 | volatile IRLAP_STATE state; /* Current state */ | |
128 | ||
129 | /* Timers used by IrLAP */ | |
130 | struct timer_list query_timer; | |
131 | struct timer_list slot_timer; | |
132 | struct timer_list discovery_timer; | |
133 | struct timer_list final_timer; | |
134 | struct timer_list poll_timer; | |
135 | struct timer_list wd_timer; | |
136 | struct timer_list backoff_timer; | |
137 | ||
138 | /* Media busy stuff */ | |
139 | struct timer_list media_busy_timer; | |
140 | int media_busy; | |
141 | ||
142 | /* Timeouts which will be different with different turn time */ | |
143 | int slot_timeout; | |
144 | int poll_timeout; | |
145 | int final_timeout; | |
146 | int wd_timeout; | |
147 | ||
148 | struct sk_buff_head txq; /* Frames to be transmitted */ | |
149 | struct sk_buff_head txq_ultra; | |
150 | ||
151 | __u8 caddr; /* Connection address */ | |
152 | __u32 saddr; /* Source device address */ | |
153 | __u32 daddr; /* Destination device address */ | |
154 | ||
155 | int retry_count; /* Times tried to establish connection */ | |
156 | int add_wait; /* True if we are waiting for frame */ | |
157 | ||
158 | __u8 connect_pending; | |
159 | __u8 disconnect_pending; | |
160 | ||
161 | /* To send a faster RR if tx queue empty */ | |
162 | #ifdef CONFIG_IRDA_FAST_RR | |
163 | int fast_RR_timeout; | |
164 | int fast_RR; | |
165 | #endif /* CONFIG_IRDA_FAST_RR */ | |
166 | ||
167 | int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */ | |
168 | int N2; /* N2 * F-timer = Negitiated link disconnect time */ | |
169 | int N3; /* Connection retry count */ | |
170 | ||
171 | int local_busy; | |
172 | int remote_busy; | |
173 | int xmitflag; | |
174 | ||
175 | __u8 vs; /* Next frame to be sent */ | |
176 | __u8 vr; /* Next frame to be received */ | |
177 | __u8 va; /* Last frame acked */ | |
178 | int window; /* Nr of I-frames allowed to send */ | |
179 | int window_size; /* Current negotiated window size */ | |
180 | ||
181 | #ifdef CONFIG_IRDA_DYNAMIC_WINDOW | |
182 | __u32 line_capacity; /* Number of bytes allowed to send */ | |
183 | __u32 bytes_left; /* Number of bytes still allowed to transmit */ | |
184 | #endif /* CONFIG_IRDA_DYNAMIC_WINDOW */ | |
185 | ||
186 | struct sk_buff_head wx_list; | |
187 | ||
188 | __u8 ack_required; | |
189 | ||
190 | /* XID parameters */ | |
191 | __u8 S; /* Number of slots */ | |
192 | __u8 slot; /* Random chosen slot */ | |
193 | __u8 s; /* Current slot */ | |
194 | int frame_sent; /* Have we sent reply? */ | |
195 | ||
196 | hashbin_t *discovery_log; | |
197 | discovery_t *discovery_cmd; | |
198 | ||
199 | __u32 speed; /* Link speed */ | |
200 | ||
201 | struct qos_info qos_tx; /* QoS requested by peer */ | |
202 | struct qos_info qos_rx; /* QoS requested by self */ | |
203 | struct qos_info *qos_dev; /* QoS supported by device */ | |
204 | ||
205 | notify_t notify; /* Callbacks to IrLMP */ | |
206 | ||
25985edc | 207 | int mtt_required; /* Minimum turnaround time required */ |
1da177e4 LT |
208 | int xbofs_delay; /* Nr of XBOF's used to MTT */ |
209 | int bofs_count; /* Negotiated extra BOFs */ | |
210 | int next_bofs; /* Negotiated extra BOFs after next frame */ | |
89da1ecf SO |
211 | |
212 | int mode; /* IrLAP mode (primary, secondary or monitor) */ | |
1da177e4 LT |
213 | }; |
214 | ||
215 | /* | |
216 | * Function prototypes | |
217 | */ | |
218 | int irlap_init(void); | |
219 | void irlap_cleanup(void); | |
220 | ||
221 | struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos, | |
222 | const char *hw_name); | |
223 | void irlap_close(struct irlap_cb *self); | |
224 | ||
225 | void irlap_connect_request(struct irlap_cb *self, __u32 daddr, | |
226 | struct qos_info *qos, int sniff); | |
227 | void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb); | |
228 | void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb); | |
229 | void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb); | |
230 | ||
231 | void irlap_data_indication(struct irlap_cb *, struct sk_buff *, int unreliable); | |
232 | void irlap_data_request(struct irlap_cb *, struct sk_buff *, int unreliable); | |
233 | ||
234 | #ifdef CONFIG_IRDA_ULTRA | |
235 | void irlap_unitdata_request(struct irlap_cb *, struct sk_buff *); | |
236 | void irlap_unitdata_indication(struct irlap_cb *, struct sk_buff *); | |
237 | #endif /* CONFIG_IRDA_ULTRA */ | |
238 | ||
239 | void irlap_disconnect_request(struct irlap_cb *); | |
240 | void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason); | |
241 | ||
242 | void irlap_status_indication(struct irlap_cb *, int quality_of_link); | |
243 | ||
244 | void irlap_test_request(__u8 *info, int len); | |
245 | ||
246 | void irlap_discovery_request(struct irlap_cb *, discovery_t *discovery); | |
247 | void irlap_discovery_confirm(struct irlap_cb *, hashbin_t *discovery_log); | |
248 | void irlap_discovery_indication(struct irlap_cb *, discovery_t *discovery); | |
249 | ||
250 | void irlap_reset_indication(struct irlap_cb *self); | |
251 | void irlap_reset_confirm(void); | |
252 | ||
253 | void irlap_update_nr_received(struct irlap_cb *, int nr); | |
254 | int irlap_validate_nr_received(struct irlap_cb *, int nr); | |
255 | int irlap_validate_ns_received(struct irlap_cb *, int ns); | |
256 | ||
257 | int irlap_generate_rand_time_slot(int S, int s); | |
258 | void irlap_initiate_connection_state(struct irlap_cb *); | |
259 | void irlap_flush_all_queues(struct irlap_cb *); | |
260 | void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *); | |
261 | ||
262 | void irlap_apply_default_connection_parameters(struct irlap_cb *self); | |
263 | void irlap_apply_connection_parameters(struct irlap_cb *self, int now); | |
264 | ||
265 | #define IRLAP_GET_HEADER_SIZE(self) (LAP_MAX_HEADER) | |
266 | #define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->txq) | |
267 | ||
268 | /* Return TRUE if the node is in primary mode (i.e. master) | |
269 | * - Jean II */ | |
270 | static inline int irlap_is_primary(struct irlap_cb *self) | |
271 | { | |
272 | int ret; | |
273 | switch(self->state) { | |
274 | case LAP_XMIT_P: | |
275 | case LAP_NRM_P: | |
276 | ret = 1; | |
277 | break; | |
278 | case LAP_XMIT_S: | |
279 | case LAP_NRM_S: | |
280 | ret = 0; | |
281 | break; | |
282 | default: | |
283 | ret = -1; | |
284 | } | |
a02cec21 | 285 | return ret; |
1da177e4 LT |
286 | } |
287 | ||
288 | /* Clear a pending IrLAP disconnect. - Jean II */ | |
289 | static inline void irlap_clear_disconnect(struct irlap_cb *self) | |
290 | { | |
291 | self->disconnect_pending = FALSE; | |
292 | } | |
293 | ||
c0cfe7fa L |
294 | /* |
295 | * Function irlap_next_state (self, state) | |
296 | * | |
297 | * Switches state and provides debug information | |
298 | * | |
299 | */ | |
300 | static inline void irlap_next_state(struct irlap_cb *self, IRLAP_STATE state) | |
301 | { | |
302 | /* | |
303 | if (!self || self->magic != LAP_MAGIC) | |
304 | return; | |
305 | ||
955a9d20 | 306 | pr_debug("next LAP state = %s\n", irlap_state[state]); |
c0cfe7fa L |
307 | */ |
308 | self->state = state; | |
309 | } | |
310 | ||
1da177e4 | 311 | #endif |