1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/kernel.h>
19#include <linux/uwb.h>
20#include <linux/export.h>
21
22#include "uwb-internal.h"
23
24
25static int uwb_radio_select_channel(struct uwb_rc *rc)
26{
27
28
29
30
31 if (rc->active_pals == 0)
32 return -1;
33 if (rc->beaconing_forced)
34 return rc->beaconing_forced;
35 return 9;
36}
37
38
39
40
41
42static void uwb_radio_channel_changed(struct uwb_rc *rc, int channel)
43{
44 struct uwb_pal *pal;
45
46 list_for_each_entry(pal, &rc->pals, node) {
47 if (pal->channel && channel != pal->channel) {
48 pal->channel = channel;
49 if (pal->channel_changed)
50 pal->channel_changed(pal, pal->channel);
51 }
52 }
53}
54
55
56
57
58
59
60
61
62static int uwb_radio_change_channel(struct uwb_rc *rc, int channel)
63{
64 int ret = 0;
65
66 if (channel == -1)
67 uwb_radio_channel_changed(rc, channel);
68
69 if (channel != rc->beaconing) {
70 if (rc->beaconing != -1 && channel != -1) {
71
72
73
74
75 ret = uwb_radio_change_channel(rc, -1);
76 if (ret < 0)
77 return ret;
78 }
79 ret = uwb_rc_beacon(rc, channel, 0);
80 }
81
82 if (channel != -1)
83 uwb_radio_channel_changed(rc, rc->beaconing);
84
85 return ret;
86}
87
88
89
90
91
92
93
94
95int uwb_radio_start(struct uwb_pal *pal)
96{
97 struct uwb_rc *rc = pal->rc;
98 int ret = 0;
99
100 mutex_lock(&rc->uwb_dev.mutex);
101
102 if (!pal->channel) {
103 pal->channel = -1;
104 rc->active_pals++;
105 ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
106 }
107
108 mutex_unlock(&rc->uwb_dev.mutex);
109 return ret;
110}
111EXPORT_SYMBOL_GPL(uwb_radio_start);
112
113
114
115
116
117
118
119void uwb_radio_stop(struct uwb_pal *pal)
120{
121 struct uwb_rc *rc = pal->rc;
122
123 mutex_lock(&rc->uwb_dev.mutex);
124
125 if (pal->channel) {
126 rc->active_pals--;
127 uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
128 pal->channel = 0;
129 }
130
131 mutex_unlock(&rc->uwb_dev.mutex);
132}
133EXPORT_SYMBOL_GPL(uwb_radio_stop);
134
135
136
137
138
139
140
141int uwb_radio_force_channel(struct uwb_rc *rc, int channel)
142{
143 int ret = 0;
144
145 mutex_lock(&rc->uwb_dev.mutex);
146
147 rc->beaconing_forced = channel;
148 ret = uwb_radio_change_channel(rc, uwb_radio_select_channel(rc));
149
150 mutex_unlock(&rc->uwb_dev.mutex);
151 return ret;
152}
153
154
155
156
157
158
159
160
161int uwb_radio_setup(struct uwb_rc *rc)
162{
163 return uwb_rc_reset(rc);
164}
165
166
167
168
169
170
171
172
173void uwb_radio_reset_state(struct uwb_rc *rc)
174{
175 struct uwb_pal *pal;
176
177 mutex_lock(&rc->uwb_dev.mutex);
178
179 list_for_each_entry(pal, &rc->pals, node) {
180 if (pal->channel) {
181 pal->channel = -1;
182 if (pal->channel_changed)
183 pal->channel_changed(pal, -1);
184 }
185 }
186
187 rc->beaconing = -1;
188 rc->scanning = -1;
189
190 mutex_unlock(&rc->uwb_dev.mutex);
191}
192
193
194
195
196
197
198
199void uwb_radio_shutdown(struct uwb_rc *rc)
200{
201 uwb_radio_reset_state(rc);
202 uwb_rc_reset(rc);
203}
204