irlap.h 9.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
/*********************************************************************
 *                
 * Filename:      irlap.h
 * Version:       0.8
 * Description:   An IrDA LAP driver for Linux
 * Status:        Experimental.
 * Author:        Dag Brattli <dagb@cs.uit.no>
 * Created at:    Mon Aug  4 20:40:53 1997
 * Modified at:   Fri Dec 10 13:21:17 1999
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
 * 
 *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
 *     All Rights Reserved.
 *     Copyright (c) 2000-2002 Jean Tourrilhes <jt@hpl.hp.com>
 *     
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version.
 *
 *     Neither Dag Brattli nor University of Troms admit liability nor
 *     provide warranty for any of this software. This material is 
 *     provided "AS-IS" and at no charge.
 *
 ********************************************************************/

#ifndef IRLAP_H
#define IRLAP_H

#include <linux/types.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/timer.h>

#include <net/irda/irqueue.h>		/* irda_queue_t */
#include <net/irda/qos.h>		/* struct qos_info */
#include <net/irda/discovery.h>		/* discovery_t */
#include <net/irda/irlap_event.h>	/* IRLAP_STATE, ... */
#include <net/irda/irmod.h>		/* struct notify_t */

#define CONFIG_IRDA_DYNAMIC_WINDOW 1

#define LAP_RELIABLE   1
#define LAP_UNRELIABLE 0

#define LAP_ADDR_HEADER 1  /* IrLAP Address Header */
#define LAP_CTRL_HEADER 1  /* IrLAP Control Header */

/* May be different when we get VFIR */
#define LAP_MAX_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)

52 53 54
/* Each IrDA device gets a random 32 bits IRLAP device address */
#define LAP_ALEN 4

L
Linus Torvalds 已提交
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
#define BROADCAST  0xffffffff /* Broadcast device address */
#define CBROADCAST 0xfe       /* Connection broadcast address */
#define XID_FORMAT 0x01       /* Discovery XID format */

/* Nobody seems to use this constant. */
#define LAP_WINDOW_SIZE 8
/* We keep the LAP queue very small to minimise the amount of buffering.
 * this improve latency and reduce resource consumption.
 * This work only because we have synchronous refilling of IrLAP through
 * the flow control mechanism (via scheduler and IrTTP).
 * 2 buffers is the minimum we can work with, one that we send while polling
 * IrTTP, and another to know that we should not send the pf bit.
 * Jean II */
#define LAP_HIGH_THRESHOLD     2
/* Some rare non TTP clients don't implement flow control, and
 * so don't comply with the above limit (and neither with this one).
 * For IAP and management, it doesn't matter, because they never transmit much.
 *.For IrLPT, this should be fixed.
 * - Jean II */
#define LAP_MAX_QUEUE 10
/* Please note that all IrDA management frames (LMP/TTP conn req/disc and
 * IAS queries) fall in the second category and are sent to LAP even if TTP
 * is stopped. This means that those frames will wait only a maximum of
 * two (2) data frames before beeing sent on the "wire", which speed up
 * new socket setup when the link is saturated.
 * Same story for two sockets competing for the medium : if one saturates
 * the LAP, when the other want to transmit it only has to wait for
 * maximum three (3) packets (2 + one scheduling), which improve performance
 * of delay sensitive applications.
 * Jean II */

#define NR_EXPECTED     1
#define NR_UNEXPECTED   0
#define NR_INVALID     -1

#define NS_EXPECTED     1
#define NS_UNEXPECTED   0
#define NS_INVALID     -1

/*
 *  Meta information passed within the IrLAP state machine
 */
struct irlap_info {
	__u8 caddr;   /* Connection address */
	__u8 control; /* Frame type */
        __u8 cmd;

	__u32 saddr;
	__u32 daddr;
	
	int pf;        /* Poll/final bit set */

	__u8  nr;      /* Sequence number of next frame expected */
	__u8  ns;      /* Sequence number of frame sent */

	int  S;        /* Number of slots */
	int  slot;     /* Random chosen slot */
	int  s;        /* Current slot */

	discovery_t *discovery; /* Discovery information */
};

/* Main structure of IrLAP */
struct irlap_cb {
	irda_queue_t q;     /* Must be first */
	magic_t magic;

	/* Device we are attached to */
	struct net_device  *netdev;
	char		hw_name[2*IFNAMSIZ + 1];

	/* Connection state */
	volatile IRLAP_STATE state;       /* Current state */

	/* Timers used by IrLAP */
	struct timer_list query_timer;
	struct timer_list slot_timer;
	struct timer_list discovery_timer;
	struct timer_list final_timer;
	struct timer_list poll_timer;
	struct timer_list wd_timer;
	struct timer_list backoff_timer;

	/* Media busy stuff */
	struct timer_list media_busy_timer;
	int media_busy;

	/* Timeouts which will be different with different turn time */
	int slot_timeout;
	int poll_timeout;
	int final_timeout;
	int wd_timeout;

	struct sk_buff_head txq;  /* Frames to be transmitted */
	struct sk_buff_head txq_ultra;

 	__u8    caddr;        /* Connection address */
	__u32   saddr;        /* Source device address */
	__u32   daddr;        /* Destination device address */

	int     retry_count;  /* Times tried to establish connection */
	int     add_wait;     /* True if we are waiting for frame */

	__u8    connect_pending;
	__u8    disconnect_pending;

	/*  To send a faster RR if tx queue empty */
#ifdef CONFIG_IRDA_FAST_RR
	int     fast_RR_timeout;
	int     fast_RR;      
#endif /* CONFIG_IRDA_FAST_RR */
	
	int N1; /* N1 * F-timer = Negitiated link disconnect warning threshold */
	int N2; /* N2 * F-timer = Negitiated link disconnect time */
	int N3; /* Connection retry count */

	int     local_busy;
	int     remote_busy;
	int     xmitflag;

	__u8    vs;            /* Next frame to be sent */
	__u8    vr;            /* Next frame to be received */
	__u8    va;            /* Last frame acked */
 	int     window;        /* Nr of I-frames allowed to send */
	int     window_size;   /* Current negotiated window size */

#ifdef CONFIG_IRDA_DYNAMIC_WINDOW
	__u32   line_capacity; /* Number of bytes allowed to send */
	__u32   bytes_left;    /* Number of bytes still allowed to transmit */
#endif /* CONFIG_IRDA_DYNAMIC_WINDOW */

	struct sk_buff_head wx_list;

	__u8    ack_required;
	
	/* XID parameters */
 	__u8    S;           /* Number of slots */
	__u8    slot;        /* Random chosen slot */
 	__u8    s;           /* Current slot */
	int     frame_sent;  /* Have we sent reply? */

	hashbin_t   *discovery_log;
 	discovery_t *discovery_cmd;

	__u32 speed;		/* Link speed */

	struct qos_info  qos_tx;   /* QoS requested by peer */
	struct qos_info  qos_rx;   /* QoS requested by self */
	struct qos_info *qos_dev;  /* QoS supported by device */

	notify_t notify; /* Callbacks to IrLMP */

	int    mtt_required;  /* Minumum turnaround time required */
	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
	int    bofs_count;    /* Negotiated extra BOFs */
	int    next_bofs;     /* Negotiated extra BOFs after next frame */
};

/* 
 *  Function prototypes 
 */
int irlap_init(void);
void irlap_cleanup(void);

struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos,
			    const char *hw_name);
void irlap_close(struct irlap_cb *self);

void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 
			   struct qos_info *qos, int sniff);
void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb);
void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb);
void irlap_connect_confirm(struct irlap_cb *, struct sk_buff *skb);

void irlap_data_indication(struct irlap_cb *, struct sk_buff *, int unreliable);
void irlap_data_request(struct irlap_cb *, struct sk_buff *, int unreliable);

#ifdef CONFIG_IRDA_ULTRA
void irlap_unitdata_request(struct irlap_cb *, struct sk_buff *);
void irlap_unitdata_indication(struct irlap_cb *, struct sk_buff *);
#endif /* CONFIG_IRDA_ULTRA */

void irlap_disconnect_request(struct irlap_cb *);
void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason);

void irlap_status_indication(struct irlap_cb *, int quality_of_link);

void irlap_test_request(__u8 *info, int len);

void irlap_discovery_request(struct irlap_cb *, discovery_t *discovery);
void irlap_discovery_confirm(struct irlap_cb *, hashbin_t *discovery_log);
void irlap_discovery_indication(struct irlap_cb *, discovery_t *discovery);

void irlap_reset_indication(struct irlap_cb *self);
void irlap_reset_confirm(void);

void irlap_update_nr_received(struct irlap_cb *, int nr);
int irlap_validate_nr_received(struct irlap_cb *, int nr);
int irlap_validate_ns_received(struct irlap_cb *, int ns);

int  irlap_generate_rand_time_slot(int S, int s);
void irlap_initiate_connection_state(struct irlap_cb *);
void irlap_flush_all_queues(struct irlap_cb *);
void irlap_wait_min_turn_around(struct irlap_cb *, struct qos_info *);

void irlap_apply_default_connection_parameters(struct irlap_cb *self);
void irlap_apply_connection_parameters(struct irlap_cb *self, int now);

#define IRLAP_GET_HEADER_SIZE(self) (LAP_MAX_HEADER)
#define IRLAP_GET_TX_QUEUE_LEN(self) skb_queue_len(&self->txq)

/* Return TRUE if the node is in primary mode (i.e. master)
 * - Jean II */
static inline int irlap_is_primary(struct irlap_cb *self)
{
	int ret;
	switch(self->state) {
	case LAP_XMIT_P:
	case LAP_NRM_P:
		ret = 1;
		break;
	case LAP_XMIT_S:
	case LAP_NRM_S:
		ret = 0;
		break;
	default:
		ret = -1;
	}
	return(ret);
}

/* Clear a pending IrLAP disconnect. - Jean II */
static inline void irlap_clear_disconnect(struct irlap_cb *self)
{
	self->disconnect_pending = FALSE;
}

#endif