3 #include <linux/if_arp.h>
4 #include <linux/sched.h>
5 #include <linux/slab.h>
6 #include <linux/export.h>
13 static void prism2_info_commtallies16(
local_info_t *local,
unsigned char *
buf,
20 "info frame\n", local->
dev->name, left);
25 #define ADD_COMM_TALLIES(name) \
26 local->comm_tallies.name += le16_to_cpu(tallies->name)
48 #undef ADD_COMM_TALLIES
53 static void prism2_info_commtallies32(
local_info_t *local,
unsigned char *buf,
60 "info frame\n", local->
dev->name, left);
65 #define ADD_COMM_TALLIES(name) \
66 local->comm_tallies.name += le32_to_cpu(tallies->name)
88 #undef ADD_COMM_TALLIES
93 static void prism2_info_commtallies(
local_info_t *local,
unsigned char *buf,
97 prism2_info_commtallies32(local, buf, left);
99 prism2_info_commtallies16(local, buf, left);
103 #ifndef PRISM2_NO_STATION_MODES
104 #ifndef PRISM2_NO_DEBUG
105 static const char* hfa384x_linkstatus_str(
u16 linkstatus)
107 switch (linkstatus) {
111 return "Disconnected";
113 return "Access point change";
115 return "Access point out of range";
117 return "Access point in range";
119 return "Association failed";
128 static void prism2_info_linkstatus(
local_info_t *local,
unsigned char *buf,
136 local->last_join_time = 0;
140 "length %d\n", local->
dev->name, left);
148 val = buf[0] | (buf[1] << 8);
150 PDEBUG(DEBUG_EXTRA,
"%s: LinkStatus=%d (%s)\n",
151 local->
dev->name, val, hfa384x_linkstatus_str(val));
161 set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info);
162 local->prev_link_status =
val;
175 if (local->last_join_time &&
177 PDEBUG(DEBUG_EXTRA,
"%s: last join request has not yet been "
178 "completed - waiting for it before issuing new one\n",
192 if (local->last_scan_results ==
NULL ||
193 local->last_scan_results_count == 0) {
194 spin_unlock_irqrestore(&local->lock, flags);
195 PDEBUG(DEBUG_EXTRA,
"%s: no scan results for host roaming\n",
200 selected = &local->last_scan_results[0];
202 if (local->preferred_ap[0] || local->preferred_ap[1] ||
203 local->preferred_ap[2] || local->preferred_ap[3] ||
204 local->preferred_ap[4] || local->preferred_ap[5]) {
206 PDEBUG(DEBUG_EXTRA,
"%s: Preferred AP BSSID %pM\n",
207 dev->
name, local->preferred_ap);
208 for (i = 0; i < local->last_scan_results_count; i++) {
209 entry = &local->last_scan_results[
i];
210 if (
memcmp(local->preferred_ap, entry->
bssid, 6) == 0)
212 PDEBUG(DEBUG_EXTRA,
"%s: using preferred AP "
213 "selection\n", dev->
name);
222 spin_unlock_irqrestore(&local->lock, flags);
224 PDEBUG(DEBUG_EXTRA,
"%s: JoinRequest: BSSID=%pM"
231 local->last_join_time =
jiffies;
235 static void hostap_report_scan_complete(
local_info_t *local)
241 wrqu.
data.length = 0;
247 local->scan_timestamp = 0;
252 static void prism2_info_scanresults(
local_info_t *local,
unsigned char *buf,
263 "length %d\n", local->
dev->name, left);
280 for (i = 0; i < new_count; i++) {
281 memcpy(&results[i], &res[i],
287 local->last_scan_type = PRISM2_SCAN;
288 prev = local->last_scan_results;
289 local->last_scan_results = results;
290 local->last_scan_results_count = new_count;
291 spin_unlock_irqrestore(&local->lock, flags);
294 hostap_report_scan_complete(local);
297 set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info);
303 static void prism2_info_hostscanresults(
local_info_t *local,
304 unsigned char *buf,
int left)
316 "length %d\n", local->
dev->name, left);
322 if (result_size == 0) {
324 "hostscanresults\n", local->
dev->name);
341 for (i = 0; i < new_count; i++) {
342 memcpy(&results[i], ptr, copy_len);
349 local->
dev->name, left, result_size);
353 local->last_scan_type = PRISM2_HOSTSCAN;
354 prev = local->last_scan_results;
355 local->last_scan_results = results;
356 local->last_scan_results_count = new_count;
357 spin_unlock_irqrestore(&local->lock, flags);
360 hostap_report_scan_complete(local);
371 #ifndef PRISM2_NO_DEBUG
376 buf = skb->
data +
sizeof(*info);
377 left = skb->
len -
sizeof(*info);
381 prism2_info_commtallies(local, buf, left);
384 #ifndef PRISM2_NO_STATION_MODES
386 prism2_info_linkstatus(local, buf, left);
390 prism2_info_scanresults(local, buf, left);
394 prism2_info_hostscanresults(local, buf, left);
398 #ifndef PRISM2_NO_DEBUG
400 PDEBUG(DEBUG_EXTRA,
"%s: INFO - len=%d type=0x%04x\n",
403 PDEBUG(DEBUG_EXTRA,
"Unknown info frame:");
404 for (i = 0; i < (left < 100 ? left : 100); i++)
405 PDEBUG2(DEBUG_EXTRA,
" %02x", buf[i]);
406 PDEBUG2(DEBUG_EXTRA,
"\n");
413 #ifndef PRISM2_NO_STATION_MODES
414 static void handle_info_queue_linkstatus(
local_info_t *local)
416 int val = local->prev_link_status;
428 "LinkStatus event\n", local->
dev->name);
430 PDEBUG(DEBUG_EXTRA,
"%s: LinkStatus: BSSID=%pM\n",
432 (
unsigned char *) local->bssid);
433 if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
455 if (connected || local->prev_linkstatus_connected)
457 local->prev_linkstatus_connected = connected;
461 static void handle_info_queue_scanresults(
local_info_t *local)
463 if (local->host_roaming == 1 && local->iw_mode ==
IW_MODE_INFRA)
464 prism2_host_roaming(local);
466 if (local->host_roaming == 2 && local->iw_mode ==
IW_MODE_INFRA &&
467 !is_zero_ether_addr(local->preferred_ap)) {
475 prism2_host_roaming(local);
487 &local->pending_info))
488 handle_info_queue_linkstatus(local);
491 &local->pending_info))
492 handle_info_queue_scanresults(local);
499 skb_queue_head_init(&local->info_list);
500 #ifndef PRISM2_NO_STATION_MODES
501 INIT_WORK(&local->info_queue, handle_info_queue);