Root/
1 | /* |
2 | * LAPB release 002 |
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 | * LAPB 001 Jonathan Naylor Started Coding |
14 | * LAPB 002 Jonathan Naylor New timer architecture. |
15 | */ |
16 | |
17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
18 | |
19 | #include <linux/errno.h> |
20 | #include <linux/types.h> |
21 | #include <linux/socket.h> |
22 | #include <linux/in.h> |
23 | #include <linux/kernel.h> |
24 | #include <linux/timer.h> |
25 | #include <linux/string.h> |
26 | #include <linux/sockios.h> |
27 | #include <linux/net.h> |
28 | #include <linux/inet.h> |
29 | #include <linux/skbuff.h> |
30 | #include <linux/slab.h> |
31 | #include <net/sock.h> |
32 | #include <asm/uaccess.h> |
33 | #include <linux/fcntl.h> |
34 | #include <linux/mm.h> |
35 | #include <linux/interrupt.h> |
36 | #include <net/lapb.h> |
37 | |
38 | /* |
39 | * This procedure is passed a buffer descriptor for an iframe. It builds |
40 | * the rest of the control part of the frame and then writes it out. |
41 | */ |
42 | static void lapb_send_iframe(struct lapb_cb *lapb, struct sk_buff *skb, int poll_bit) |
43 | { |
44 | unsigned char *frame; |
45 | |
46 | if (!skb) |
47 | return; |
48 | |
49 | if (lapb->mode & LAPB_EXTENDED) { |
50 | frame = skb_push(skb, 2); |
51 | |
52 | frame[0] = LAPB_I; |
53 | frame[0] |= lapb->vs << 1; |
54 | frame[1] = poll_bit ? LAPB_EPF : 0; |
55 | frame[1] |= lapb->vr << 1; |
56 | } else { |
57 | frame = skb_push(skb, 1); |
58 | |
59 | *frame = LAPB_I; |
60 | *frame |= poll_bit ? LAPB_SPF : 0; |
61 | *frame |= lapb->vr << 5; |
62 | *frame |= lapb->vs << 1; |
63 | } |
64 | |
65 | lapb_dbg(1, "(%p) S%d TX I(%d) S%d R%d\n", |
66 | lapb->dev, lapb->state, poll_bit, lapb->vs, lapb->vr); |
67 | |
68 | lapb_transmit_buffer(lapb, skb, LAPB_COMMAND); |
69 | } |
70 | |
71 | void lapb_kick(struct lapb_cb *lapb) |
72 | { |
73 | struct sk_buff *skb, *skbn; |
74 | unsigned short modulus, start, end; |
75 | |
76 | modulus = (lapb->mode & LAPB_EXTENDED) ? LAPB_EMODULUS : LAPB_SMODULUS; |
77 | start = !skb_peek(&lapb->ack_queue) ? lapb->va : lapb->vs; |
78 | end = (lapb->va + lapb->window) % modulus; |
79 | |
80 | if (!(lapb->condition & LAPB_PEER_RX_BUSY_CONDITION) && |
81 | start != end && skb_peek(&lapb->write_queue)) { |
82 | lapb->vs = start; |
83 | |
84 | /* |
85 | * Dequeue the frame and copy it. |
86 | */ |
87 | skb = skb_dequeue(&lapb->write_queue); |
88 | |
89 | do { |
90 | if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { |
91 | skb_queue_head(&lapb->write_queue, skb); |
92 | break; |
93 | } |
94 | |
95 | if (skb->sk) |
96 | skb_set_owner_w(skbn, skb->sk); |
97 | |
98 | /* |
99 | * Transmit the frame copy. |
100 | */ |
101 | lapb_send_iframe(lapb, skbn, LAPB_POLLOFF); |
102 | |
103 | lapb->vs = (lapb->vs + 1) % modulus; |
104 | |
105 | /* |
106 | * Requeue the original data frame. |
107 | */ |
108 | skb_queue_tail(&lapb->ack_queue, skb); |
109 | |
110 | } while (lapb->vs != end && (skb = skb_dequeue(&lapb->write_queue)) != NULL); |
111 | |
112 | lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; |
113 | |
114 | if (!lapb_t1timer_running(lapb)) |
115 | lapb_start_t1timer(lapb); |
116 | } |
117 | } |
118 | |
119 | void lapb_transmit_buffer(struct lapb_cb *lapb, struct sk_buff *skb, int type) |
120 | { |
121 | unsigned char *ptr; |
122 | |
123 | ptr = skb_push(skb, 1); |
124 | |
125 | if (lapb->mode & LAPB_MLP) { |
126 | if (lapb->mode & LAPB_DCE) { |
127 | if (type == LAPB_COMMAND) |
128 | *ptr = LAPB_ADDR_C; |
129 | if (type == LAPB_RESPONSE) |
130 | *ptr = LAPB_ADDR_D; |
131 | } else { |
132 | if (type == LAPB_COMMAND) |
133 | *ptr = LAPB_ADDR_D; |
134 | if (type == LAPB_RESPONSE) |
135 | *ptr = LAPB_ADDR_C; |
136 | } |
137 | } else { |
138 | if (lapb->mode & LAPB_DCE) { |
139 | if (type == LAPB_COMMAND) |
140 | *ptr = LAPB_ADDR_A; |
141 | if (type == LAPB_RESPONSE) |
142 | *ptr = LAPB_ADDR_B; |
143 | } else { |
144 | if (type == LAPB_COMMAND) |
145 | *ptr = LAPB_ADDR_B; |
146 | if (type == LAPB_RESPONSE) |
147 | *ptr = LAPB_ADDR_A; |
148 | } |
149 | } |
150 | |
151 | lapb_dbg(2, "(%p) S%d TX %02X %02X %02X\n", |
152 | lapb->dev, lapb->state, |
153 | skb->data[0], skb->data[1], skb->data[2]); |
154 | |
155 | if (!lapb_data_transmit(lapb, skb)) |
156 | kfree_skb(skb); |
157 | } |
158 | |
159 | void lapb_establish_data_link(struct lapb_cb *lapb) |
160 | { |
161 | lapb->condition = 0x00; |
162 | lapb->n2count = 0; |
163 | |
164 | if (lapb->mode & LAPB_EXTENDED) { |
165 | lapb_dbg(1, "(%p) S%d TX SABME(1)\n", lapb->dev, lapb->state); |
166 | lapb_send_control(lapb, LAPB_SABME, LAPB_POLLON, LAPB_COMMAND); |
167 | } else { |
168 | lapb_dbg(1, "(%p) S%d TX SABM(1)\n", lapb->dev, lapb->state); |
169 | lapb_send_control(lapb, LAPB_SABM, LAPB_POLLON, LAPB_COMMAND); |
170 | } |
171 | |
172 | lapb_start_t1timer(lapb); |
173 | lapb_stop_t2timer(lapb); |
174 | } |
175 | |
176 | void lapb_enquiry_response(struct lapb_cb *lapb) |
177 | { |
178 | lapb_dbg(1, "(%p) S%d TX RR(1) R%d\n", |
179 | lapb->dev, lapb->state, lapb->vr); |
180 | |
181 | lapb_send_control(lapb, LAPB_RR, LAPB_POLLON, LAPB_RESPONSE); |
182 | |
183 | lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; |
184 | } |
185 | |
186 | void lapb_timeout_response(struct lapb_cb *lapb) |
187 | { |
188 | lapb_dbg(1, "(%p) S%d TX RR(0) R%d\n", |
189 | lapb->dev, lapb->state, lapb->vr); |
190 | lapb_send_control(lapb, LAPB_RR, LAPB_POLLOFF, LAPB_RESPONSE); |
191 | |
192 | lapb->condition &= ~LAPB_ACK_PENDING_CONDITION; |
193 | } |
194 | |
195 | void lapb_check_iframes_acked(struct lapb_cb *lapb, unsigned short nr) |
196 | { |
197 | if (lapb->vs == nr) { |
198 | lapb_frames_acked(lapb, nr); |
199 | lapb_stop_t1timer(lapb); |
200 | lapb->n2count = 0; |
201 | } else if (lapb->va != nr) { |
202 | lapb_frames_acked(lapb, nr); |
203 | lapb_start_t1timer(lapb); |
204 | } |
205 | } |
206 | |
207 | void lapb_check_need_response(struct lapb_cb *lapb, int type, int pf) |
208 | { |
209 | if (type == LAPB_COMMAND && pf) |
210 | lapb_enquiry_response(lapb); |
211 | } |
212 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9