1/*
2 *	AX.25 release 037
3 *
4 *	This code REQUIRES 2.1.15 or higher/ NET3.038
5 *
6 *	This module:
7 *		This module is free software; you can redistribute it and/or
8 *		modify it under the terms of the GNU General Public License
9 *		as published by the Free Software Foundation; either version
10 *		2 of the License, or (at your option) any later version.
11 *
12 *	History
13 *	AX.25 028a	Jonathan(G4KLX)	New state machine based on SDL diagrams.
14 *	AX.25 028b	Jonathan(G4KLX)	Extracted AX25 control block from the
15 *					sock structure.
16 *	AX.25 029	Alan(GW4PTS)	Switched to KA9Q constant names.
17 *	AX.25 031	Joerg(DL1BKE)	Added DAMA support
18 *	AX.25 032	Joerg(DL1BKE)	Fixed DAMA timeout bug
19 *	AX.25 033	Jonathan(G4KLX)	Modularisation functions.
20 *	AX.25 035	Frederic(F1OAT)	Support for pseudo-digipeating.
21 *	AX.25 036	Jonathan(G4KLX)	Split Standard and DAMA code into separate files.
22 *			Joerg(DL1BKE)	Fixed DAMA Slave. We are *required* to start with
23 *					standard AX.25 mode.
24 *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
25 *                      Tomi(OH2BNS)    Fixed heartbeat expiry (check ax25_dev).
26 */
27
28#include <linux/config.h>
29#include <linux/errno.h>
30#include <linux/types.h>
31#include <linux/socket.h>
32#include <linux/in.h>
33#include <linux/kernel.h>
34#include <linux/sched.h>
35#include <linux/timer.h>
36#include <linux/string.h>
37#include <linux/sockios.h>
38#include <linux/net.h>
39#include <net/ax25.h>
40#include <linux/inet.h>
41#include <linux/netdevice.h>
42#include <linux/skbuff.h>
43#include <net/sock.h>
44#include <asm/uaccess.h>
45#include <asm/system.h>
46#include <linux/fcntl.h>
47#include <linux/mm.h>
48#include <linux/interrupt.h>
49
50static void ax25_heartbeat_expiry(unsigned long);
51static void ax25_t1timer_expiry(unsigned long);
52static void ax25_t2timer_expiry(unsigned long);
53static void ax25_t3timer_expiry(unsigned long);
54static void ax25_idletimer_expiry(unsigned long);
55
56void ax25_start_heartbeat(ax25_cb *ax25)
57{
58	del_timer(&ax25->timer);
59
60	ax25->timer.data     = (unsigned long)ax25;
61	ax25->timer.function = &ax25_heartbeat_expiry;
62	ax25->timer.expires  = jiffies + 5 * HZ;
63
64	add_timer(&ax25->timer);
65}
66
67void ax25_start_t1timer(ax25_cb *ax25)
68{
69	del_timer(&ax25->t1timer);
70
71	ax25->t1timer.data     = (unsigned long)ax25;
72	ax25->t1timer.function = &ax25_t1timer_expiry;
73	ax25->t1timer.expires  = jiffies + ax25->t1;
74
75	add_timer(&ax25->t1timer);
76}
77
78void ax25_start_t2timer(ax25_cb *ax25)
79{
80	del_timer(&ax25->t2timer);
81
82	ax25->t2timer.data     = (unsigned long)ax25;
83	ax25->t2timer.function = &ax25_t2timer_expiry;
84	ax25->t2timer.expires  = jiffies + ax25->t2;
85
86	add_timer(&ax25->t2timer);
87}
88
89void ax25_start_t3timer(ax25_cb *ax25)
90{
91	del_timer(&ax25->t3timer);
92
93	if (ax25->t3 > 0) {
94		ax25->t3timer.data     = (unsigned long)ax25;
95		ax25->t3timer.function = &ax25_t3timer_expiry;
96		ax25->t3timer.expires  = jiffies + ax25->t3;
97
98		add_timer(&ax25->t3timer);
99	}
100}
101
102void ax25_start_idletimer(ax25_cb *ax25)
103{
104	del_timer(&ax25->idletimer);
105
106	if (ax25->idle > 0) {
107		ax25->idletimer.data     = (unsigned long)ax25;
108		ax25->idletimer.function = &ax25_idletimer_expiry;
109		ax25->idletimer.expires  = jiffies + ax25->idle;
110
111		add_timer(&ax25->idletimer);
112	}
113}
114
115void ax25_stop_heartbeat(ax25_cb *ax25)
116{
117	del_timer(&ax25->timer);
118}
119
120void ax25_stop_t1timer(ax25_cb *ax25)
121{
122	del_timer(&ax25->t1timer);
123}
124
125void ax25_stop_t2timer(ax25_cb *ax25)
126{
127	del_timer(&ax25->t2timer);
128}
129
130void ax25_stop_t3timer(ax25_cb *ax25)
131{
132	del_timer(&ax25->t3timer);
133}
134
135void ax25_stop_idletimer(ax25_cb *ax25)
136{
137	del_timer(&ax25->idletimer);
138}
139
140int ax25_t1timer_running(ax25_cb *ax25)
141{
142	return timer_pending(&ax25->t1timer);
143}
144
145unsigned long ax25_display_timer(struct timer_list *timer)
146{
147	if (!timer_pending(timer))
148		return 0;
149
150	return timer->expires - jiffies;
151}
152
153static void ax25_heartbeat_expiry(unsigned long param)
154{
155	ax25_cb *ax25 = (ax25_cb *)param;
156	int proto = AX25_PROTO_STD_SIMPLEX;
157
158	if (ax25->ax25_dev)
159		proto = ax25->ax25_dev->values[AX25_VALUES_PROTOCOL];
160
161	switch (proto) {
162		case AX25_PROTO_STD_SIMPLEX:
163		case AX25_PROTO_STD_DUPLEX:
164			ax25_std_heartbeat_expiry(ax25);
165			break;
166
167#ifdef CONFIG_AX25_DAMA_SLAVE
168		case AX25_PROTO_DAMA_SLAVE:
169			if (ax25->ax25_dev->dama.slave)
170				ax25_ds_heartbeat_expiry(ax25);
171			else
172				ax25_std_heartbeat_expiry(ax25);
173			break;
174#endif
175	}
176}
177
178static void ax25_t1timer_expiry(unsigned long param)
179{
180	ax25_cb *ax25 = (ax25_cb *)param;
181
182	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
183		case AX25_PROTO_STD_SIMPLEX:
184		case AX25_PROTO_STD_DUPLEX:
185			ax25_std_t1timer_expiry(ax25);
186			break;
187
188#ifdef CONFIG_AX25_DAMA_SLAVE
189		case AX25_PROTO_DAMA_SLAVE:
190			if (!ax25->ax25_dev->dama.slave)
191				ax25_std_t1timer_expiry(ax25);
192			break;
193#endif
194	}
195}
196
197static void ax25_t2timer_expiry(unsigned long param)
198{
199	ax25_cb *ax25 = (ax25_cb *)param;
200
201	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
202		case AX25_PROTO_STD_SIMPLEX:
203		case AX25_PROTO_STD_DUPLEX:
204			ax25_std_t2timer_expiry(ax25);
205			break;
206
207#ifdef CONFIG_AX25_DAMA_SLAVE
208		case AX25_PROTO_DAMA_SLAVE:
209			if (!ax25->ax25_dev->dama.slave)
210				ax25_std_t2timer_expiry(ax25);
211			break;
212#endif
213	}
214}
215
216static void ax25_t3timer_expiry(unsigned long param)
217{
218	ax25_cb *ax25 = (ax25_cb *)param;
219
220	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
221		case AX25_PROTO_STD_SIMPLEX:
222		case AX25_PROTO_STD_DUPLEX:
223			ax25_std_t3timer_expiry(ax25);
224			break;
225
226#ifdef CONFIG_AX25_DAMA_SLAVE
227		case AX25_PROTO_DAMA_SLAVE:
228			if (ax25->ax25_dev->dama.slave)
229				ax25_ds_t3timer_expiry(ax25);
230			else
231				ax25_std_t3timer_expiry(ax25);
232			break;
233#endif
234	}
235}
236
237static void ax25_idletimer_expiry(unsigned long param)
238{
239	ax25_cb *ax25 = (ax25_cb *)param;
240
241	switch (ax25->ax25_dev->values[AX25_VALUES_PROTOCOL]) {
242		case AX25_PROTO_STD_SIMPLEX:
243		case AX25_PROTO_STD_DUPLEX:
244			ax25_std_idletimer_expiry(ax25);
245			break;
246
247#ifdef CONFIG_AX25_DAMA_SLAVE
248		case AX25_PROTO_DAMA_SLAVE:
249			if (ax25->ax25_dev->dama.slave)
250				ax25_ds_idletimer_expiry(ax25);
251			else
252				ax25_std_idletimer_expiry(ax25);
253			break;
254#endif
255	}
256}
257