iscan_buf_t *dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf) { iscan_buf_t *iscanbuf_alloc = 0; iscan_buf_t *iscanbuf_head; dhd_iscan_lock(); iscanbuf_alloc = kmalloc(sizeof(iscan_buf_t), GFP_ATOMIC); if (iscanbuf_alloc == NULL) goto fail; iscanbuf_alloc->next = NULL; iscanbuf_head = *iscanbuf; DHD_ISCAN(("%s: addr of allocated node = 0x%X" "addr of iscanbuf_head = 0x%X dhd = 0x%X\n", __func__, iscanbuf_alloc, iscanbuf_head, dhd)); if (iscanbuf_head == NULL) { *iscanbuf = iscanbuf_alloc; DHD_ISCAN(("%s: Head is allocated\n", __func__)); goto fail; } while (iscanbuf_head->next) iscanbuf_head = iscanbuf_head->next; iscanbuf_head->next = iscanbuf_alloc; fail: dhd_iscan_unlock(); return iscanbuf_alloc; }
iscan_buf_t * dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf) { iscan_buf_t *iscanbuf_alloc = 0; iscan_buf_t *iscanbuf_head; DHD_TRACE(("%s: Entered\n", __FUNCTION__)); dhd_iscan_lock(); iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t)); if (iscanbuf_alloc == NULL) goto fail; iscanbuf_alloc->next = NULL; iscanbuf_head = *iscanbuf; DHD_ISCAN(("%s: addr of allocated node = 0x%X" "addr of iscanbuf_head = 0x%X dhd = 0x%X\n", __FUNCTION__, iscanbuf_alloc, iscanbuf_head, dhd)); if (iscanbuf_head == NULL) { *iscanbuf = iscanbuf_alloc; DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__)); goto fail; } while (iscanbuf_head->next) iscanbuf_head = iscanbuf_head->next; iscanbuf_head->next = iscanbuf_alloc; fail: dhd_iscan_unlock(); return iscanbuf_alloc; }
static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) { wl_iscan_results_t *list_buf; wl_iscan_results_t list; wl_scan_results_t *results; iscan_buf_t *iscan_cur; int status = -1; dhd_pub_t *dhd = dhd_bus_pub(dhdp); int rc; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain); if (!iscan_cur) { DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__)); dhd_iscan_free_buf(dhdp, 0); dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT); dhd_ind_scan_confirm(dhdp, FALSE); goto fail; } dhd_iscan_lock(); memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf; results = &list_buf->results; results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; results->version = 0; results->count = 0; memset(&list, 0, sizeof(list)); list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); rc = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN, FALSE, 0); results->buflen = dtoh32(results->buflen); results->version = dtoh32(results->version); *scan_count = results->count = dtoh32(results->count); status = dtoh32(list_buf->status); DHD_TRACE(("%s: Got %d resuls\n", __FUNCTION__, results->count)); dhd_iscan_unlock(); if (!(*scan_count)) { dhd_iscan_free_buf(dhdp, iscan_cur); } fail: return status; }
int dhd_iscan_remove_duplicates(void *dhdp, iscan_buf_t *iscan_cur) { int i = 0; wl_iscan_results_t *list; wl_scan_results_t *results; wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; dhd_iscan_lock(); DHD_ISCAN(("%s: Scan cache before delete\n", __func__)); dhd_iscan_print_cache(iscan_cur); if (!iscan_cur) goto done; list = (wl_iscan_results_t *)iscan_cur->iscan_buf; if (!list) goto done; results = (wl_scan_results_t *)&list->results; if (!results) goto done; if (results->version != WL_BSS_INFO_VERSION) { DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n", __func__, results->version)); goto done; } bi = results->bss_info; for (i = 0; i < results->count; i++) { if (!bi) break; DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n", __func__, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur); bi = (wl_bss_info_t *)((unsigned long)bi + bi->length); } done: DHD_ISCAN(("%s: Scan cache after delete\n", __func__)); dhd_iscan_print_cache(iscan_cur); dhd_iscan_unlock(); return 0; }
static int dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) { wl_iscan_results_t *list_buf; wl_iscan_results_t list; wl_scan_results_t *results; iscan_buf_t *iscan_cur; int status = -1; dhd_pub_t *dhd = dhd_bus_pub(dhdp); int rc; iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain); if (!iscan_cur) { DHD_ERROR(("%s: Failed to allocate node\n", __func__)); dhd_iscan_free_buf(dhdp, 0); dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT); goto fail; } dhd_iscan_lock(); memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); list_buf = (wl_iscan_results_t *) iscan_cur->iscan_buf; results = &list_buf->results; results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; results->version = 0; results->count = 0; memset(&list, 0, sizeof(list)); list.results.buflen = WLC_IW_ISCAN_MAXLEN; bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); results->buflen = results->buflen; results->version = results->version; *scan_count = results->count = results->count; status = list_buf->status; dhd_iscan_unlock(); if (!(*scan_count)) dhd_iscan_free_buf(dhdp, iscan_cur); else dhd_iscan_remove_duplicates(dhdp, iscan_cur); fail: return status; }
/* * print scan cache * print partial iscan_skip list differently */ int dhd_iscan_print_cache(iscan_buf_t *iscan_skip) { int i = 0, l = 0; iscan_buf_t *iscan_cur; wl_iscan_results_t *list; wl_scan_results_t *results; wl_bss_info_t UNALIGNED *bi; dhd_iscan_lock(); iscan_cur = dhd_iscan_result_buf(); while (iscan_cur) { list = (wl_iscan_results_t *)iscan_cur->iscan_buf; if (!list) break; results = (wl_scan_results_t *)&list->results; if (!results) break; if (results->version != WL_BSS_INFO_VERSION) { DHD_ISCAN(("%s: results->version %d != " "WL_BSS_INFO_VERSION\n", __func__, results->version)); goto done; } bi = results->bss_info; for (i = 0; i < results->count; i++) { if (!bi) break; DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", iscan_cur != iscan_skip ? "BSS" : "bss", l, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi = (wl_bss_info_t *)((unsigned long)bi + bi->length); } iscan_cur = iscan_cur->next; l++; } done: dhd_iscan_unlock(); return 0; }
void dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete) { iscan_buf_t *iscanbuf_free = 0; iscan_buf_t *iscanbuf_prv = 0; iscan_buf_t *iscanbuf_cur; dhd_pub_t *dhd = dhd_bus_pub(dhdp); DHD_TRACE(("%s: Entered\n", __FUNCTION__)); dhd_iscan_lock(); iscanbuf_cur = iscan_chain; /* If iscan_delete is null then delete the entire * chain or else delete specific one provided */ if (!iscan_delete) { while (iscanbuf_cur) { iscanbuf_free = iscanbuf_cur; iscanbuf_cur = iscanbuf_cur->next; iscanbuf_free->next = 0; MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t)); } iscan_chain = 0; } else { while (iscanbuf_cur) { if (iscanbuf_cur == iscan_delete) break; iscanbuf_prv = iscanbuf_cur; iscanbuf_cur = iscanbuf_cur->next; } if (iscanbuf_prv) iscanbuf_prv->next = iscan_delete->next; iscan_delete->next = 0; MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t)); if (!iscanbuf_prv) iscan_chain = 0; } dhd_iscan_unlock(); }
void dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete) { iscan_buf_t *iscanbuf_free = 0; iscan_buf_t *iscanbuf_prv = 0; iscan_buf_t *iscanbuf_cur = iscan_chain; dhd_pub_t *dhd = dhd_bus_pub(dhdp); dhd_iscan_lock(); /* If iscan_delete is null then delete the entire * chain or else delete specific one provided */ if (!iscan_delete) { while (iscanbuf_cur) { iscanbuf_free = iscanbuf_cur; iscanbuf_cur = iscanbuf_cur->next; iscanbuf_free->next = 0; kfree(iscanbuf_free); } iscan_chain = 0; } else { while (iscanbuf_cur) { if (iscanbuf_cur == iscan_delete) break; iscanbuf_prv = iscanbuf_cur; iscanbuf_cur = iscanbuf_cur->next; } if (iscanbuf_prv) iscanbuf_prv->next = iscan_delete->next; iscan_delete->next = 0; kfree(iscan_delete); if (!iscanbuf_prv) iscan_chain = 0; } dhd_iscan_unlock(); }
/* * delete disappeared AP from specific scan cache */ int dhd_iscan_delete_bss(/* TBD void *dhdp, */ void *addr) { int i = 0, j = 0, l = 0; iscan_buf_t *iscan_cur; wl_iscan_results_t *list; wl_scan_results_t *results; wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; uchar *s_addr = addr; DHD_TRACE(("%s: Entered\n", __FUNCTION__)); dhd_iscan_lock(); DHD_TRACE(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n", __FUNCTION__, s_addr[0], s_addr[1], s_addr[2], s_addr[3], s_addr[4], s_addr[5])); DHD_TRACE(("%s: Scan cache before delete\n", __FUNCTION__)); iscan_cur = dhd_iscan_result_buf(); while (iscan_cur) { list = (wl_iscan_results_t *)iscan_cur->iscan_buf; if (!list) break; results = (wl_scan_results_t *)&list->results; if (!results) break; if (results->version != WL_BSS_INFO_VERSION) { DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n", __FUNCTION__, results->version)); goto done; } bi = results->bss_info; for (i = 0; i < results->count; i++) { if (!bi) break; if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) { DHD_TRACE(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", __FUNCTION__, l, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_new = bi; bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); for (j = i; j < results->count; j++) { DHD_TRACE(("%s: Moved up BSS[%2.2d:%2.2d]" " %X:%X:%X:%X:%X:%X\n", __FUNCTION__, l, j, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_next = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); bcopy(bi, bi_new, dtoh32(bi->length)); bi_new = (wl_bss_info_t *)((uintptr)bi_new + dtoh32(bi_new->length)); bi = bi_next; } results->count--; if (results->count == 0) { /* Prune now empty partial scan list */ goto done; } break; } bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); } iscan_cur = iscan_cur->next; l++; } done: DHD_TRACE(("%s: Scan cache after delete\n", __FUNCTION__)); dhd_iscan_unlock(); return 0; }
/* * delete disappeared AP from specific scan cache but skip partial * list in iscan_skip */ int dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip) { int i = 0, j = 0, l = 0; iscan_buf_t *iscan_cur; wl_iscan_results_t *list; wl_scan_results_t *results; wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; unsigned char *s_addr = addr; dhd_iscan_lock(); DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n", __func__, s_addr[0], s_addr[1], s_addr[2], s_addr[3], s_addr[4], s_addr[5])); iscan_cur = dhd_iscan_result_buf(); while (iscan_cur) { if (iscan_cur != iscan_skip) { list = (wl_iscan_results_t *)iscan_cur->iscan_buf; if (!list) break; results = (wl_scan_results_t *)&list->results; if (!results) break; if (results->version != WL_BSS_INFO_VERSION) { DHD_ERROR(("%s: results->version %d != " "WL_BSS_INFO_VERSION\n", __func__, results->version)); goto done; } bi = results->bss_info; for (i = 0; i < results->count; i++) { if (!bi) break; if (!memcmp (bi->BSSID.octet, addr, ETH_ALEN)) { DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] " "%X:%X:%X:%X:%X:%X\n", __func__, l, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_new = bi; bi = (wl_bss_info_t *)((unsigned long) bi + bi->length); /* if(bi && bi_new) { memcpy(bi_new, bi, results->buflen - bi_new->length); results->buflen -= bi_new->length; } */ results->buflen -= bi_new->length; results->count--; for (j = i; j < results->count; j++) { if (bi && bi_new) { DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d]" "%X:%X:%X:%X:%X:%X\n", __func__, l, j, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); bi_next = (wl_bss_info_t *)((unsigned long)bi + bi->length); memcpy(bi_new, bi, bi->length); bi_new = (wl_bss_info_t *)((unsigned long)bi_new + bi_new-> length); bi = bi_next; } } if (results->count == 0) { /* Prune now empty partial scan list */ dhd_iscan_free_buf(dhdp, iscan_cur); goto done; } break; } bi = (wl_bss_info_t *)((unsigned long)bi + bi->length); } } iscan_cur = iscan_cur->next; l++; } done: dhd_iscan_unlock(); return 0; }