summaryrefslogtreecommitdiff
path: root/lib/scanmerge.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/scanmerge.c')
-rw-r--r--lib/scanmerge.c343
1 files changed, 343 insertions, 0 deletions
diff --git a/lib/scanmerge.c b/lib/scanmerge.c
new file mode 100644
index 00000000..36f17a2c
--- /dev/null
+++ b/lib/scanmerge.c
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*-------------------------------------------------------------------*/
+#include "includes.h"
+#include "scanmerge.h"
+#include "shlist.h"
+
+#define IS_HIDDEN_AP(a) (((a)->ssid_len == 0) || ((a)->ssid[0] == '\0'))
+
+scan_ssid_t *scan_get_ssid( scan_result_t *res_ptr )
+{
+ static scan_ssid_t ssid_temp;
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ const u8 *res_ie;
+
+ res_ie = wpa_scan_get_ie(res_ptr, WLAN_EID_SSID);
+ if (!res_ie)
+ return NULL;
+ ssid_temp.ssid_len = (size_t)res_ie[1];
+ os_memcpy(ssid_temp.ssid, (res_ie + 2), ssid_temp.ssid_len);
+#else
+ ssid_temp.ssid_len = res_ptr->ssid_len;
+ os_memcpy(ssid_temp.ssid, res_ptr->ssid, ssid_temp.ssid_len);
+#endif
+ return &ssid_temp;
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_init
+Routine Description: Inits scan merge list
+Arguments:
+ mydrv - pointer to private driver data structure
+Return Value:
+-----------------------------------------------------------------------------*/
+void scan_init( struct wpa_driver_ti_data *mydrv )
+{
+ mydrv->last_scan = -1;
+ shListInitList(&(mydrv->scan_merge_list));
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_free
+Routine Description: Frees scan structure private data
+Arguments:
+ ptr - pointer to private data structure
+Return Value:
+-----------------------------------------------------------------------------*/
+static void scan_free( void *ptr )
+{
+ os_free(ptr);
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_exit
+Routine Description: Cleans scan merge list
+Arguments:
+ mydrv - pointer to private driver data structure
+Return Value:
+-----------------------------------------------------------------------------*/
+void scan_exit( struct wpa_driver_ti_data *mydrv )
+{
+ shListDelAllItems(&(mydrv->scan_merge_list), scan_free);
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_count
+Routine Description: Gives number of list elements
+Arguments:
+ mydrv - pointer to private driver data structure
+Return Value: Number of elements in the list
+-----------------------------------------------------------------------------*/
+unsigned long scan_count( struct wpa_driver_ti_data *mydrv )
+{
+ return shListGetCount(&(mydrv->scan_merge_list));
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_equal
+Routine Description: Compares bssid of scan result and scan merge structure
+Arguments:
+ val - pointer to scan result structure
+ idata - pointer to scan merge structure
+Return Value: 1 - if equal, 0 - if not
+-----------------------------------------------------------------------------*/
+static int scan_equal( void *val, void *idata )
+{
+ scan_ssid_t n_ssid, l_ssid, *p_ssid;
+ scan_result_t *new_res = (scan_result_t *)val;
+ scan_result_t *lst_res =
+ (scan_result_t *)(&(((scan_merge_t *)idata)->scanres));
+ int ret;
+ size_t len;
+
+ p_ssid = scan_get_ssid(new_res);
+ if (!p_ssid)
+ return 0;
+ os_memcpy(&n_ssid, p_ssid, sizeof(scan_ssid_t));
+ p_ssid = scan_get_ssid(lst_res);
+ if (!p_ssid)
+ return 0;
+ os_memcpy(&l_ssid, p_ssid, sizeof(scan_ssid_t));
+
+ len = (IS_HIDDEN_AP(&n_ssid) || IS_HIDDEN_AP(&l_ssid)) ?
+ 0 : n_ssid.ssid_len;
+ ret = ((l_ssid.ssid_len != n_ssid.ssid_len) && (len != 0)) ||
+ (os_memcmp(new_res->bssid, lst_res->bssid, ETH_ALEN) ||
+ os_memcmp(n_ssid.ssid, l_ssid.ssid, len));
+ return !ret;
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: copy_scan_res
+Routine Description: copies scan result structure to scan merge list item
+Arguments:
+ dst - pointer to scan result structure in the list
+ src - source pointer to scan result structure
+Return Value: NONE
+-----------------------------------------------------------------------------*/
+void copy_scan_res( scan_result_t *dst, scan_result_t *src )
+{
+#ifdef WPA_SUPPLICANT_VER_0_5_X
+ if( IS_HIDDEN_AP(src) ) {
+ os_memcpy(src->ssid, dst->ssid, dst->ssid_len);
+ src->ssid_len = dst->ssid_len;
+ }
+#endif
+ os_memcpy(dst, src, sizeof(scan_result_t));
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_add
+Routine Description: adds scan result structure to scan merge list
+Arguments:
+ head - pointer to scan merge list head
+ res_ptr - pointer to scan result structure
+Return Value: Pointer to scan merge item
+-----------------------------------------------------------------------------*/
+static scan_merge_t *scan_add( SHLIST *head, scan_result_t *res_ptr )
+{
+ scan_merge_t *scan_ptr;
+ unsigned size = 0;
+
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ size += res_ptr->ie_len;
+#endif
+ scan_ptr = (scan_merge_t *)os_malloc(sizeof(scan_merge_t) + size);
+ if( !scan_ptr )
+ return( NULL );
+ os_memcpy(&(scan_ptr->scanres), res_ptr, sizeof(scan_result_t) + size);
+ scan_ptr->count = SCAN_MERGE_COUNT;
+ shListInsLastItem(head, (void *)scan_ptr);
+ return scan_ptr;
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_find
+Routine Description: Looks for scan merge item in scan results array
+Arguments:
+ scan_ptr - pointer to scan merge item
+ results - pointer to scan results array
+ number_items - current number of items
+Return Value: 1 - if item was found, 0 - otherwise
+-----------------------------------------------------------------------------*/
+static int scan_find( scan_merge_t *scan_ptr, scan_result_t *results,
+ unsigned int number_items )
+{
+ unsigned int i;
+
+ for(i=0;( i < number_items );i++) {
+ if( scan_equal(&(results[i]), scan_ptr) )
+ return 1;
+ }
+ return 0;
+}
+
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+/*-----------------------------------------------------------------------------
+Routine Name: scan_dup
+Routine Description: Create copy of scan results entry
+Arguments:
+ res_ptr - pointer to scan result item
+Return Value: pointer to new scan result item, or NULL
+-----------------------------------------------------------------------------*/
+static scan_result_t *scan_dup( scan_result_t *res_ptr )
+{
+ unsigned size;
+ scan_result_t *new_ptr;
+
+ if (!res_ptr)
+ return NULL;
+
+ size = sizeof(scan_result_t) + res_ptr->ie_len;
+ new_ptr = os_malloc(size);
+ if (!new_ptr)
+ return NULL;
+ if (res_ptr) {
+ os_memcpy(new_ptr, res_ptr, size);
+ }
+ return new_ptr;
+}
+#endif
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_merge
+Routine Description: Merges current scan results with previous
+Arguments:
+ mydrv - pointer to private driver data structure
+ results - pointer to scan results array
+ number_items - current number of items
+ max_size - maximum namber of items
+Return Value: Merged number of items
+-----------------------------------------------------------------------------*/
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+unsigned int scan_merge( struct wpa_driver_ti_data *mydrv,
+ scan_result_t **results, int force_flag,
+ unsigned int number_items, unsigned int max_size )
+#else
+unsigned int scan_merge( struct wpa_driver_ti_data *mydrv,
+ scan_result_t *results, int force_flag,
+ unsigned int number_items, unsigned int max_size )
+#endif
+{
+ SHLIST *head = &(mydrv->scan_merge_list);
+ SHLIST *item, *del_item;
+ scan_result_t *res_ptr;
+ scan_merge_t *scan_ptr;
+ unsigned int i;
+
+ /* Prepare items for removal */
+ item = shListGetFirstItem(head);
+ while( item != NULL ) {
+ scan_ptr = (scan_merge_t *)(item->data);
+ if( scan_ptr->count != 0 )
+ scan_ptr->count--;
+ item = shListGetNextItem(head, item);
+ }
+
+ for(i=0;( i < number_items );i++) { /* Find/Add new items */
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ res_ptr = results[i];
+#else
+ res_ptr = &(results[i]);
+#endif
+ item = shListFindItem( head, res_ptr, scan_equal );
+ if( item ) {
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ scan_ssid_t *p_ssid;
+ scan_result_t *new_ptr;
+#endif
+ scan_ptr = (scan_merge_t *)(item->data);
+ copy_scan_res(&(scan_ptr->scanres), res_ptr);
+ scan_ptr->count = SCAN_MERGE_COUNT;
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ p_ssid = scan_get_ssid(res_ptr);
+ if (p_ssid && IS_HIDDEN_AP(p_ssid)) {
+ new_ptr = scan_dup(res_ptr);
+ if (new_ptr) {
+ results[i] = new_ptr;
+ os_free(res_ptr);
+ }
+ }
+#endif
+ }
+ else {
+ scan_add(head, res_ptr);
+ }
+ }
+
+ item = shListGetFirstItem( head ); /* Add/Remove missing items */
+ while( item != NULL ) {
+ del_item = NULL;
+ scan_ptr = (scan_merge_t *)(item->data);
+ if( scan_ptr->count != SCAN_MERGE_COUNT ) {
+ if( !force_flag && ((scan_ptr->count == 0) ||
+ (mydrv->last_scan == SCAN_TYPE_NORMAL_ACTIVE)) ) {
+ del_item = item;
+ }
+ else {
+ if( number_items < max_size ) {
+#ifdef WPA_SUPPLICANT_VER_0_6_X
+ res_ptr = scan_dup(&(scan_ptr->scanres));
+ if (res_ptr) {
+ results[number_items] = res_ptr;
+ number_items++;
+ }
+#else
+ os_memcpy(&(results[number_items]),
+ &(scan_ptr->scanres), sizeof(scan_result_t));
+ number_items++;
+#endif
+ }
+ }
+ }
+ item = shListGetNextItem(head, item);
+ shListDelItem(head, del_item, scan_free);
+ }
+
+ return( number_items );
+}
+
+/*-----------------------------------------------------------------------------
+Routine Name: scan_get_by_bssid
+Routine Description: Gets scan_result pointer to item by bssid
+Arguments:
+ mydrv - pointer to private driver data structure
+ bssid - pointer to bssid value
+Return Value: pointer to scan_result item
+-----------------------------------------------------------------------------*/
+scan_result_t *scan_get_by_bssid( struct wpa_driver_ti_data *mydrv, u8 *bssid )
+{
+ SHLIST *head = &(mydrv->scan_merge_list);
+ SHLIST *item;
+ scan_result_t *cur_res;
+ scan_ssid_t *p_ssid;
+
+ item = shListGetFirstItem(head);
+ if( item == NULL )
+ return( NULL );
+ do {
+ cur_res = (scan_result_t *)&(((scan_merge_t *)(item->data))->scanres);
+ p_ssid = scan_get_ssid(cur_res);
+ if( (!os_memcmp(cur_res->bssid, bssid, ETH_ALEN)) &&
+ (!IS_HIDDEN_AP(p_ssid)) ) {
+ return( cur_res );
+ }
+ item = shListGetNextItem(head, item);
+ } while( item != NULL );
+
+ return( NULL );
+}