static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); tSirBssDescription *descriptor = &scan_result->BssDescriptor; struct iw_event event; char *current_event = scanInfo->start; char *end = scanInfo->end; char *last_event; char *current_pad; v_U16_t ie_length = 0; v_U16_t capabilityInfo; char *modestr; int error; char custom[MAX_CUSTOM_LEN]; char *p; hddLog( LOG1, "hdd_IndicateScanResult %02x:%02x:%02x:%02x:%02x:%02x", descriptor->bssId[0], descriptor->bssId[1], descriptor->bssId[2], descriptor->bssId[3], descriptor->bssId[4], descriptor->bssId[5]); error = 0; last_event = current_event; vos_mem_zero(&event, sizeof (event)); event.cmd = SIOCGIWAP; event.u.ap_addr.sa_family = ARPHRD_ETHER; vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId, sizeof (descriptor->bssId)); current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_ADDR_LEN); if (last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWAP "); return -E2BIG; } last_event = current_event; vos_mem_zero(&event, sizeof (struct iw_event)); event.cmd = SIOCGIWNAME; switch (descriptor->nwType) { case eSIR_11A_NW_TYPE: modestr = "a"; break; case eSIR_11B_NW_TYPE: modestr = "b"; break; case eSIR_11G_NW_TYPE: modestr = "g"; break; case eSIR_11N_NW_TYPE: modestr = "n"; break; default: hddLog( LOGW, "%s: Unknown network type [%d]", __func__, descriptor->nwType); modestr = "?"; break; } snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr); current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_CHAR_LEN); if (last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWNAME"); return -E2BIG; } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); event.cmd = SIOCGIWFREQ; event.u.freq.m = descriptor->channelId; event.u.freq.e = 0; event.u.freq.i = 0; current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_FREQ_LEN); if (last_event == current_event) { return -E2BIG; } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); event.cmd = SIOCGIWMODE; capabilityInfo = descriptor->capabilityInfo; if (SIR_MAC_GET_ESS(capabilityInfo)) { event.u.mode = IW_MODE_INFRA; } else if (SIR_MAC_GET_IBSS(capabilityInfo)) { event.u.mode = IW_MODE_ADHOC; } else { event.u.mode = IW_MODE_AUTO; } current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_UINT_LEN); if (last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWMODE"); return -E2BIG; } ie_length = GET_IE_LEN_IN_BSS( descriptor->length ); if (ie_length > 0) { static tDot11fBeaconIEs dot11BeaconIEs; tDot11fIESSID *pDot11SSID; tDot11fIESuppRates *pDot11SuppRates; tDot11fIEExtSuppRates *pDot11ExtSuppRates; tDot11fIEHTCaps *pDot11IEHTCaps; int numBasicRates = 0; int maxNumRates = 0; pDot11IEHTCaps = NULL; dot11fUnpackBeaconIEs ((tpAniSirGlobal) hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs); pDot11SSID = &dot11BeaconIEs.SSID; if (pDot11SSID->present ) { last_event = current_event; vos_mem_zero (&event, sizeof (struct iw_event)); event.cmd = SIOCGIWESSID; event.u.data.flags = 1; event.u.data.length = scan_result->ssId.length; current_event = iwe_stream_add_point (scanInfo->info,current_event, end, &event, (char *)scan_result->ssId.ssId); if(last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); return -E2BIG; } } if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, ¤t_event, scanInfo ) < 0 ) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); return -E2BIG; } last_event = current_event; current_pad = current_event + IW_EV_LCP_LEN; vos_mem_zero( &event, sizeof (struct iw_event)); event.cmd = SIOCGIWRATE; pDot11SuppRates = &dot11BeaconIEs.SuppRates; if (pDot11SuppRates->present ) { int i; numBasicRates = pDot11SuppRates->num_rates; for (i=0; i<pDot11SuppRates->num_rates; i++) { if (0 != (pDot11SuppRates->rates[i] & 0x7F)) { event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( &pDot11SuppRates->rates[i]); current_pad = iwe_stream_add_value (scanInfo->info,current_event, current_pad, end, &event, IW_EV_PARAM_LEN); } } } pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates; if (pDot11ExtSuppRates->present ) { int i,no_of_rates; maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates; maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES); if((maxNumRates - numBasicRates) > MAX_RATES) { no_of_rates = MAX_RATES; hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates "); } else { no_of_rates = maxNumRates - numBasicRates; } for ( i=0; i< no_of_rates ; i++ ) { if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F)) { event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( &pDot11ExtSuppRates->rates[i]); current_pad = iwe_stream_add_value (scanInfo->info,current_event, current_pad, end, &event, IW_EV_PARAM_LEN); } } } if ((current_pad - current_event) >= IW_EV_LCP_LEN) { current_event = current_pad; } else { if (last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for SIOCGIWRATE"); return -E2BIG; } } last_event = current_event; vos_mem_zero (&event, sizeof (struct iw_event)); event.cmd = SIOCGIWENCODE; if (SIR_MAC_GET_PRIVACY(capabilityInfo)) { event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; } else { event.u.data.flags = IW_ENCODE_DISABLED; } event.u.data.length = 0; current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid); if(last_event == current_event) { return -E2BIG; } } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); event.cmd = IWEVQUAL; event.u.qual.qual = descriptor->rssi; event.u.qual.noise = descriptor->sinr; if (( eConnectionState_Associated == pAdapter->sessionCtx.station.conn_info.connState ) && ( VOS_TRUE == vos_mem_compare(descriptor->bssId, pAdapter->sessionCtx.station.conn_info.bssId, WNI_CFG_BSSID_LEN))) { event.u.qual.level = pAdapter->rssi; } else { event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0); } event.u.qual.updated = IW_QUAL_ALL_UPDATED; current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_QUAL_LEN); if(last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVQUAL"); return -E2BIG; } event.cmd = IWEVCUSTOM; p = custom; p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu", vos_timer_get_system_ticks() - descriptor->nReceivedTime); event.u.data.length = p - custom; current_event = iwe_stream_add_point (scanInfo->info,current_event, end, &event, custom); if(last_event == current_event) { hddLog( LOGW, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)"); return -E2BIG; } scanInfo->start = current_event; return 0; }
static eHalStatus hdd_IndicateScanResult(hdd_scan_info_t *scanInfo, tCsrScanResultInfo *scan_result) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(scanInfo->dev) ; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); tSirBssDescription *descriptor = &scan_result->BssDescriptor; struct iw_event event; char *current_event = scanInfo->start; char *end = scanInfo->end; char *last_event; char *current_pad; v_U16_t ie_length = 0; v_U16_t capabilityInfo; char *modestr; int error; char custom[MAX_CUSTOM_LEN]; char *p; hddLog( LOG1, "hdd_IndicateScanResult " MAC_ADDRESS_STR, MAC_ADDR_ARRAY(descriptor->bssId)); error = 0; last_event = current_event; vos_mem_zero(&event, sizeof (event)); /* BSSID */ event.cmd = SIOCGIWAP; event.u.ap_addr.sa_family = ARPHRD_ETHER; vos_mem_copy (event.u.ap_addr.sa_data, descriptor->bssId, sizeof (descriptor->bssId)); current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_ADDR_LEN); if (last_event == current_event) { /* no space to add event */ /* Error code may be E2BIG */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWAP "); return -E2BIG; } last_event = current_event; vos_mem_zero(&event, sizeof (struct iw_event)); /* Protocol Name */ event.cmd = SIOCGIWNAME; switch (descriptor->nwType) { case eSIR_11A_NW_TYPE: modestr = "a"; break; case eSIR_11B_NW_TYPE: modestr = "b"; break; case eSIR_11G_NW_TYPE: modestr = "g"; break; case eSIR_11N_NW_TYPE: modestr = "n"; break; default: hddLog( LOGW, "%s: Unknown network type [%d]", __func__, descriptor->nwType); modestr = "?"; break; } snprintf(event.u.name, IFNAMSIZ, "IEEE 802.11%s", modestr); current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_CHAR_LEN); if (last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWNAME"); /* Error code, may be E2BIG */ return -E2BIG; } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); /*Freq*/ event.cmd = SIOCGIWFREQ; event.u.freq.m = descriptor->channelId; event.u.freq.e = 0; event.u.freq.i = 0; current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_FREQ_LEN); if (last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWFREQ"); return -E2BIG; } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); /* BSS Mode */ event.cmd = SIOCGIWMODE; capabilityInfo = descriptor->capabilityInfo; if (SIR_MAC_GET_ESS(capabilityInfo)) { event.u.mode = IW_MODE_MASTER; } else if (SIR_MAC_GET_IBSS(capabilityInfo)) { event.u.mode = IW_MODE_ADHOC; } else { /* neither ESS or IBSS */ event.u.mode = IW_MODE_AUTO; } current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_UINT_LEN); if (last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWMODE"); return -E2BIG; } /* To extract SSID */ ie_length = GET_IE_LEN_IN_BSS( descriptor->length ); if (ie_length > 0) { /* dot11BeaconIEs is a large struct, so we make it static to avoid stack overflow. This API is only invoked via ioctl, so it is serialized by the kernel rtnl_lock and hence does not need to be reentrant */ static tDot11fBeaconIEs dot11BeaconIEs; tDot11fIESSID *pDot11SSID; tDot11fIESuppRates *pDot11SuppRates; tDot11fIEExtSuppRates *pDot11ExtSuppRates; tDot11fIEHTCaps *pDot11IEHTCaps; int numBasicRates = 0; int maxNumRates = 0; pDot11IEHTCaps = NULL; dot11fUnpackBeaconIEs ((tpAniSirGlobal) hHal, (tANI_U8 *) descriptor->ieFields, ie_length, &dot11BeaconIEs); pDot11SSID = &dot11BeaconIEs.SSID; if (pDot11SSID->present ) { last_event = current_event; vos_mem_zero (&event, sizeof (struct iw_event)); event.cmd = SIOCGIWESSID; event.u.data.flags = 1; event.u.data.length = scan_result->ssId.length; current_event = iwe_stream_add_point (scanInfo->info,current_event, end, &event, (char *)scan_result->ssId.ssId); if(last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); return -E2BIG; } } if( hdd_GetWPARSNIEs( ( tANI_U8 *) descriptor->ieFields, ie_length, &last_event, ¤t_event, scanInfo ) < 0 ) { hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWESSID"); return -E2BIG; } last_event = current_event; current_pad = current_event + IW_EV_LCP_LEN; vos_mem_zero( &event, sizeof (struct iw_event)); /*Rates*/ event.cmd = SIOCGIWRATE; pDot11SuppRates = &dot11BeaconIEs.SuppRates; if (pDot11SuppRates->present ) { int i; numBasicRates = pDot11SuppRates->num_rates; for (i=0; i<pDot11SuppRates->num_rates; i++) { if (0 != (pDot11SuppRates->rates[i] & 0x7F)) { event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( &pDot11SuppRates->rates[i]); current_pad = iwe_stream_add_value (scanInfo->info,current_event, current_pad, end, &event, IW_EV_PARAM_LEN); } } } pDot11ExtSuppRates = &dot11BeaconIEs.ExtSuppRates; if (pDot11ExtSuppRates->present ) { int i,no_of_rates; maxNumRates = numBasicRates + pDot11ExtSuppRates->num_rates; /* Check to make sure the total number of rates doesn't exceed IW_MAX_BITRATES */ maxNumRates = VOS_MIN(maxNumRates , IW_MAX_BITRATES); if((maxNumRates - numBasicRates) > MAX_RATES) { no_of_rates = MAX_RATES; hddLog( LOGW, "Accessing array out of bound that array is pDot11ExtSuppRates->rates "); } else { no_of_rates = maxNumRates - numBasicRates; } for ( i=0; i< no_of_rates ; i++ ) { if (0 != (pDot11ExtSuppRates->rates[i] & 0x7F)) { event.u.bitrate.value = hdd_TranslateABGRateToMbpsRate ( &pDot11ExtSuppRates->rates[i]); current_pad = iwe_stream_add_value (scanInfo->info,current_event, current_pad, end, &event, IW_EV_PARAM_LEN); } } } if ((current_pad - current_event) >= IW_EV_LCP_LEN) { current_event = current_pad; } else { if (last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWRATE"); return -E2BIG; } } last_event = current_event; vos_mem_zero (&event, sizeof (struct iw_event)); event.cmd = SIOCGIWENCODE; if (SIR_MAC_GET_PRIVACY(capabilityInfo)) { event.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; } else { event.u.data.flags = IW_ENCODE_DISABLED; } event.u.data.length = 0; current_event = iwe_stream_add_point(scanInfo->info,current_event, end, &event, (char *)pDot11SSID->ssid); if(last_event == current_event) { /* no space to add event Error code, may be E2BIG */ hddLog( LOGE, "hdd_IndicateScanResult: no space for SIOCGIWENCODE"); return -E2BIG; } } last_event = current_event; vos_mem_zero( &event, sizeof (struct iw_event)); /*RSSI*/ event.cmd = IWEVQUAL; event.u.qual.qual = descriptor->rssi; event.u.qual.noise = descriptor->sinr; /*To keep the rssi icon of the connected AP in the scan window *and the rssi icon of the wireless networks in sync */ if (( eConnectionState_Associated == pAdapter->sessionCtx.station.conn_info.connState ) && ( VOS_TRUE == vos_mem_compare(descriptor->bssId, pAdapter->sessionCtx.station.conn_info.bssId, VOS_MAC_ADDR_SIZE))) { event.u.qual.level = pAdapter->rssi; } else { event.u.qual.level = VOS_MIN ((descriptor->rssi + descriptor->sinr), 0); } event.u.qual.updated = IW_QUAL_ALL_UPDATED; current_event = iwe_stream_add_event(scanInfo->info,current_event, end, &event, IW_EV_QUAL_LEN); if(last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVQUAL"); return -E2BIG; } /* AGE */ event.cmd = IWEVCUSTOM; p = custom; p += scnprintf(p, MAX_CUSTOM_LEN, " Age: %lu", vos_timer_get_system_ticks() - descriptor->nReceivedTime); event.u.data.length = p - custom; current_event = iwe_stream_add_point (scanInfo->info,current_event, end, &event, custom); if(last_event == current_event) { /* no space to add event */ hddLog( LOGE, "hdd_IndicateScanResult: no space for IWEVCUSTOM (age)"); return -E2BIG; } scanInfo->start = current_event; return 0; }