diff options
Diffstat (limited to 'firmwares/wifishield/wifiHD/src/wl_cm.c')
-rw-r--r-- | firmwares/wifishield/wifiHD/src/wl_cm.c | 431 |
1 files changed, 0 insertions, 431 deletions
diff --git a/firmwares/wifishield/wifiHD/src/wl_cm.c b/firmwares/wifishield/wifiHD/src/wl_cm.c deleted file mode 100644 index ebc0e45..0000000 --- a/firmwares/wifishield/wifiHD/src/wl_cm.c +++ /dev/null @@ -1,431 +0,0 @@ -/* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */ - -/*! \page License - * Copyright (C) 2009, H&D Wireless AB All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * 3. The name of H&D Wireless AB may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND - * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "wl_cm.h" -#include "util.h" -#include <string.h> -#include "debug.h" - -/** Roaming configuration parameters **/ - -/*! The ROAMING_RSSI_THRESHOLD setting defines how bad the current - * signal strength should be before we'll consider roaming to an AP - * with better signal strength. The objective is to stay on the - * current AP as long as the RSSI is decent, even if there are other - * APs in the same BSS with better RSSI available. - * If ROAMING_RSSI_THRESHOLD is too high we might roam unecessarily. - * If ROAMING_RSSI_THRESHOLD is too low we might not roam in time to - * avoid packet loss. This also impacts power consumption, staying - * too long with an AP with poor RSSI will consume more power. - * Unit is dBm. - */ -#define ROAMING_RSSI_THRESHOLD -65 - -/*! The ROAMING_RSSI_DIFF setting defines how much better - * than the currently associated AP a new AP must be before - * we'll attempt to roam over to the new AP. - * If ROAMING_RSSI_DIFF is too high it might be too hard - * to roam (important if the STA is expected to move - * quickly through different AP coverage areas). - * If ROAMING_RSSI_DIFF is too low we might bounce between - * two APs with similar signal strengths. - * Unit is dBm. - */ -#define ROAMING_RSSI_DIFF 10 - -# include "printf-stdarg.h" -#include "ard_utils.h" -#include "debug.h" - -/** \defgroup wl_cm Connection Manager - * - * These functions are used to configure and control the WiFi connetion - * manager. - * - * - * @{ - */ - -struct cm_candidate { - struct wl_ssid_t ssid; - struct wl_mac_addr_t bssid; -}; - -struct cm { - cm_scan_cb_t *scan_cb; - cm_conn_cb_t *conn_cb; - cm_disconn_cb_t *disconn_cb; - void* ctx; - uint8_t enabled; - struct cm_candidate candidate; -}; - - -/** - * This function can be modified to pick a network based on - * application specific criteria. - * - * If the SSID can not be found in the scan list it will be - * assumed to be a hidden SSID and the wl_connect() command - * will be called to attempt to probe for the network and - * connect to it. - */ -static struct wl_network_t* -find_best_candidate(struct cm* cm) -{ - struct wl_network_list_t* netlist; - struct wl_network_t *best_net = NULL; - uint8_t i; - - if (wl_get_network_list(&netlist) != WL_SUCCESS) - return NULL; - - if (netlist->cnt == 0) - return NULL; - - for (i = 0; i < netlist->cnt; i++) { - /* match on ssid */ - if (cm->candidate.ssid.len) - if (!equal_ssid(&cm->candidate.ssid, - &netlist->net[i]->ssid)) - continue; - - /* match bssid */ - if (strncmp((char*) cm->candidate.bssid.octet, - "\xff\xff\xff\xff\xff\xff", 6)) - if (!equal_bssid(&cm->candidate.bssid, - &netlist->net[i]->bssid)) - continue; - /* check for best rssi. */ - if ( best_net && - ( best_net->rssi > netlist->net[i]->rssi) ) { - continue; - } - best_net = netlist->net[i]; - } - - return best_net; -} - - -/** - * - */ -static void -select_net(struct cm* cm) -{ - struct wl_network_t *candidate_net; - struct wl_network_t *current_net; - struct wl_ssid_t *ssid_p; - - int ret; - - /* Nothing to do */ - if (0 == cm->candidate.ssid.len) { - return; - } - - current_net = wl_get_current_network(); - candidate_net = find_best_candidate(cm); - - /* Connected to the candidate? ... */ - if ( current_net == candidate_net ) { - if ( current_net ) { - /* ...yes, dont change. */ - - return; - } - } - - /* Roaming checks */ - if (current_net && candidate_net) { - /* Are we changing BSSs? */ - if ( equal_ssid(&candidate_net->ssid, - ¤t_net->ssid)) { - - /* ...no. Does the currently connected - * net have a decent RSSI?...*/ - if ( current_net->rssi > ROAMING_RSSI_THRESHOLD ) { - /* ...yes, stay with it. */ - return; - } - /* ...no. Does the candidate have - * sufficiently better RSSI to - * motivate a switch to it? */ - if ( candidate_net->rssi < current_net->rssi + - ROAMING_RSSI_DIFF) { - return; - } - /* ...yes, try to roam to candidate_net */ - CM_DPRINTF("CM: Roaming from rssi %d to %d\n", - current_net->rssi, - candidate_net->rssi); - } - } - /* a candidate is found */ - if (candidate_net) { - /* We connect to a specific bssid here because - * find_best_candidate() might have picked a - * particulare AP among many with the same SSID. - * wl_connect() would pick one of them at random. - */ - ret = wl_connect_bssid(candidate_net->bssid); - } - /* no candidate found */ - else { - CM_DPRINTF("CM: No candidate found for ssid \"%s\"\n", - ssid2str(&cm->candidate.ssid)); - /* Might be a hidden SSID so we try to connect to it. - * wl_connect() will trigger a directed scan - * for the SSID in this case. - */ - ssid_p = &cm->candidate.ssid; - ret = wl_connect(ssid_p->ssid, ssid_p->len); - } - switch (ret) { - case WL_SUCCESS : - return; - case WL_BUSY: - wl_disconnect(); - return; - case WL_RETRY: - break; - default : - CM_DPRINTF("CM: failed to connect\n"); - break; - } - - /* some operation failed or no candidate found */ - if (wl_scan() != WL_SUCCESS) - CM_DPRINTF("CM: failed to scan\n"); -} - - -/** - * - */ -static void -wl_scan_complete_cb(void* ctx) -{ - struct cm *cm = ctx; - - CM_DPRINTF("CM: scan completed\n"); - - if (cm->scan_cb) - cm->scan_cb(cm->ctx); - - if ( 0 == cm->enabled ) { - return; - } - select_net(cm); -} - -/** - * - */ -static void -wl_media_connected_cb(void* ctx) -{ - struct cm *cm = ctx; - struct wl_network_t *net = wl_get_current_network(); - CM_DPRINTF("CM: connected to %s\n", ssid2str(&net->ssid)); - LINK_LED_ON(); - ERROR_LED_OFF(); - if (cm->conn_cb) - cm->conn_cb(net, cm->ctx); -} - - -/** - * - */ -static void -wl_conn_failure_cb(void* ctx) -{ - struct cm *cm = ctx; - CM_DPRINTF("CM: connect failed, scanning\n"); - ERROR_LED_ON(); - LINK_LED_OFF(); - - if ( 0 == cm->enabled ) { - return; - } - if (wl_scan() != WL_SUCCESS) - /* should never happen */ - CM_DPRINTF("CM: could not start scan after connect fail!\n"); -} - - -/** - * - */ -static void -wl_conn_lost_cb(void* ctx) -{ - struct cm *cm = ctx; - CM_DPRINTF("CM: connection lost, scanning\n"); - LINK_LED_OFF(); - if (cm->disconn_cb) - cm->disconn_cb(cm->ctx); - - if ( 0 == cm->enabled ) { - return; - } - if (wl_scan() != WL_SUCCESS) - /* should never happen */ - CM_DPRINTF("CM: could not start scan after connect lost!\n"); -} - - -/** - * - */ -static void -wl_event_cb(struct wl_event_t event, void* ctx) -{ - struct cm *cm = ctx; - - switch (event.id) { - case WL_EVENT_MEDIA_CONNECTED: - wl_media_connected_cb(cm); - break; - - case WL_EVENT_CONN_FAILURE: - wl_conn_failure_cb(cm); - break; - - case WL_EVENT_MEDIA_DISCONNECTED: - CM_DPRINTF("CM: disconnected\n"); - wl_conn_lost_cb(cm); - break; - - case WL_EVENT_SCAN_COMPLETE: - wl_scan_complete_cb(cm); - break; - - default: - CM_DPRINTF("CM: unhandled event\n"); - }; -} - -static struct cm *cm = NULL; - - -/** - * Doesn't actually start the CM, just initializing. CM will run whenever - * an valid ssid is set through wl_cm_set_network() and wl_cm_start() - * has been called. - */ -wl_err_t -wl_cm_init(cm_scan_cb_t scan_cb, - cm_conn_cb_t conn_cb, - cm_disconn_cb_t disconn_cb, - void* ctx) -{ - if (cm != NULL) - return WL_FAILURE; - - cm = calloc(1, sizeof(struct cm)); - if (cm == NULL) { - CM_DPRINTF("CM: out of memory\n"); - return WL_FAILURE; - } - - if (wl_register_event_cb(wl_event_cb, cm) != WL_SUCCESS) { - CM_DPRINTF("CM: could not register event cb\n"); - return WL_FAILURE; - } - - cm->scan_cb = scan_cb; - cm->conn_cb = conn_cb; - cm->disconn_cb = disconn_cb; - cm->enabled = 0; - cm->ctx = ctx; - - CM_DPRINTF("CM: initialized\n"); - return WL_SUCCESS; -} - -wl_err_t -wl_cm_start(void) { - if (NULL == cm) - return WL_FAILURE; - - cm->enabled = 1; - return WL_SUCCESS; -} - -wl_err_t -wl_cm_stop(void) { - if (NULL == cm) - return WL_FAILURE; - - cm->enabled = 0; - return WL_SUCCESS; -} - - -/** - * Set the desired network which the connection manager should try to - * connect to. - * - * The ssid and bssid of the desired network should be specified. The ssid and - * bssid will be matched against the networks found during scan. If any - * parameter is null, it will always match. If both parameters are null, - * the first found network will be chosen. - * - * @param ssid The ssid of the desired network. If null, any ssid will match. - * @param bssid The bssid of the desired network. If null, any bssid will match. - * - */ -wl_err_t -wl_cm_set_network(struct wl_ssid_t *ssid, struct wl_mac_addr_t *bssid) -{ - if (cm == NULL) - return WL_FAILURE; - - if (ssid) - memcpy(&cm->candidate.ssid, ssid, sizeof(cm->candidate.ssid)); - else - cm->candidate.ssid.len = 0; - - if (bssid) - memcpy(&cm->candidate.bssid, bssid, - sizeof(cm->candidate.bssid)); - else - memset(&cm->candidate.bssid, 0xff, sizeof(cm->candidate.bssid)); - - if (cm->candidate.ssid.len) - wl_scan(); - - return WL_SUCCESS; -} -/* - * @} - */ |