Ejemplo n.º 1
0
Archivo: iwctl.c Proyecto: 7799/linux
/*
 * Wireless Handler : get scan results
 */
int iwctl_giwscan(struct net_device *dev, struct iw_request_info *info,
		union iwreq_data *wrqu, char *extra)
{
	struct iw_point *wrq = &wrqu->data;
	int ii;
	int jj;
	int kk;
	struct vnt_private *pDevice = netdev_priv(dev);
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	PKnownBSS pBSS;
	PWLAN_IE_SSID pItemSSID;
	PWLAN_IE_SUPP_RATES pSuppRates;
	PWLAN_IE_SUPP_RATES pExtSuppRates;
	char *current_ev = extra;
	char *end_buf = extra + IW_SCAN_MAX_DATA;
	char *current_val = NULL;
	struct iw_event iwe;
	long ldBm;

	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN\n");

	if (pMgmt == NULL)
		return -EFAULT;

	if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
		// In scanning..
		return -EAGAIN;
	}
	pBSS = &(pMgmt->sBSSList[0]);
	for (ii = 0, jj = 0; jj < MAX_BSS_NUM; jj++) {
		if (current_ev >= end_buf)
			break;
		pBSS = &(pMgmt->sBSSList[jj]);
		if (pBSS->bActive) {
			// ADD mac address
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWAP;
			iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
			memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN);
			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
			// ADD ssid
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWESSID;
			pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
			iwe.u.data.length = pItemSSID->len;
			iwe.u.data.flags = 1;
			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);
			// ADD mode
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWMODE;
			if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo))
				iwe.u.mode = IW_MODE_INFRA;
			else
				iwe.u.mode = IW_MODE_ADHOC;
			iwe.len = IW_EV_UINT_LEN;
			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
			// ADD frequency
			pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates;
			pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates;
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWFREQ;
			iwe.u.freq.m = pBSS->uChannel;
			iwe.u.freq.e = 0;
			iwe.u.freq.i = 0;
			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
			{
				int f = (int)pBSS->uChannel - 1;
				if (f < 0)
					f = 0;
				iwe.u.freq.m = frequency_list[f] * 100000;
				iwe.u.freq.e = 1;
			}
			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
			// ADD quality
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = IWEVQUAL;
			RFvRSSITodBm(pDevice, (u8)(pBSS->uRSSI), &ldBm);
			iwe.u.qual.level = ldBm;
			iwe.u.qual.noise = 0;

			if (-ldBm < 50)
				iwe.u.qual.qual = 100;
			else  if (-ldBm > 90)
				iwe.u.qual.qual = 0;
			else
				iwe.u.qual.qual = (40 - (-ldBm - 50)) * 100 / 40;
			iwe.u.qual.updated = 7;

			current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
			// ADD encryption
			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWENCODE;
			iwe.u.data.length = 0;
			if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo))
				iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
			else
				iwe.u.data.flags = IW_ENCODE_DISABLED;
			current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pItemSSID->abySSID);

			memset(&iwe, 0, sizeof(iwe));
			iwe.cmd = SIOCGIWRATE;
			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
			current_val = current_ev + IW_EV_LCP_LEN;

			for (kk = 0; kk < 12; kk++) {
				if (pSuppRates->abyRates[kk] == 0)
					break;
				// Bit rate given in 500 kb/s units (+ 0x80)
				iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000);
				current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
			}
			for (kk = 0; kk < 8; kk++) {
				if (pExtSuppRates->abyRates[kk] == 0)
					break;
				// Bit rate given in 500 kb/s units (+ 0x80)
				iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000);
				current_val = iwe_stream_add_value(info, current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
			}

			if ((current_val - current_ev) > IW_EV_LCP_LEN)
				current_ev = current_val;

			if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
				memset(&iwe, 0, sizeof(iwe));
				iwe.cmd = IWEVGENIE;
				iwe.u.data.length = pBSS->wWPALen;
				current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byWPAIE);
			}

			if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) {
				memset(&iwe, 0, sizeof(iwe));
				iwe.cmd = IWEVGENIE;
				iwe.u.data.length = pBSS->wRSNLen;
				current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, pBSS->byRSNIE);
			}
		}
	} // for
	wrq->length = current_ev - extra;
	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 %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, &current_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;
}
Ejemplo n.º 3
0
static int wlcompat_get_scan(struct net_device *dev,
			 struct iw_request_info *info,
			 union iwreq_data *wrqu,
			 char *extra)
{
	wl_scan_results_t *results = (wl_scan_results_t *) buf;
	wl_bss_info_t *bss_info;
	char *info_ptr;
	char *current_ev = extra;
	char *current_val;
	char *end_buf = extra + IW_SCAN_MAX_DATA;
	struct iw_event iwe;
	int i, j;

	if (wl_ioctl(dev, WLC_SCAN_RESULTS, buf, WLC_IOCTL_MAXLEN) < 0)
		return -EAGAIN;
	
	bss_info = &(results->bss_info[0]);
	info_ptr = (char *) bss_info;
	for (i = 0; i < results->count; i++) {

		/* send the cell address (must be sent first) */
		iwe.cmd = SIOCGIWAP;
		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
		memcpy(&iwe.u.ap_addr.sa_data, &bss_info->BSSID, sizeof(bss_info->BSSID));
		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
		
		/* send the ESSID */
		iwe.cmd = SIOCGIWESSID;
		iwe.u.data.length = bss_info->SSID_len;
		if (iwe.u.data.length > IW_ESSID_MAX_SIZE)
			iwe.u.data.length = IW_ESSID_MAX_SIZE;
		iwe.u.data.flags = 1;
		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, bss_info->SSID);

		/* send frequency/channel info */
		iwe.cmd = SIOCGIWFREQ;
		iwe.u.freq.e = 0;
		iwe.u.freq.m = bss_info->channel;
		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);

		/* add quality statistics */
		iwe.cmd = IWEVQUAL;
		iwe.u.qual.level = bss_info->RSSI;
		iwe.u.qual.noise = bss_info->phy_noise;
		iwe.u.qual.qual = 0;
		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
	
		/* send rate information */
		iwe.cmd = SIOCGIWRATE;
		current_val = current_ev + IW_EV_LCP_LEN;
		iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
		
		for(j = 0 ; j < bss_info->rateset.count ; j++) {
			iwe.u.bitrate.value = ((bss_info->rateset.rates[j] & 0x7f) * 500000);
			current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
		}
		if((current_val - current_ev) > IW_EV_LCP_LEN)
			current_ev = current_val;

		info_ptr += sizeof(wl_bss_info_t);
		if (bss_info->ie_length % 4)
			info_ptr += bss_info->ie_length + 4 - (bss_info->ie_length % 4);
		else
			info_ptr += bss_info->ie_length;
		bss_info = (wl_bss_info_t *) info_ptr;
	}
	
	wrqu->data.length = (current_ev - extra);
	wrqu->data.flags = 0;

	return 0;
}
Ejemplo n.º 4
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, &current_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;
}
Ejemplo n.º 5
0
int iwctl_giwscan(struct net_device *dev,
             struct iw_request_info *info,
			 struct iw_point *wrq,
             char *extra)
{
    int ii, jj, kk;
	PSDevice	        pDevice = (PSDevice)netdev_priv(dev);
    PSMgmtObject        pMgmt = &(pDevice->sMgmtObj);
    PKnownBSS           pBSS;
    PWLAN_IE_SSID       pItemSSID;
    PWLAN_IE_SUPP_RATES pSuppRates, pExtSuppRates;
	char *current_ev = extra;
	char *end_buf = extra + IW_SCAN_MAX_DATA;
	char *current_val = NULL;
	struct iw_event iwe;
	long ldBm;
	char buf[MAX_WPA_IE_LEN * 2 + 30];

    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " SIOCGIWSCAN\n");

    if (pMgmt->eScanState ==  WMAC_IS_SCANNING) {
        
		return -EAGAIN;
	}
	pBSS = &(pMgmt->sBSSList[0]);
    for (ii = 0, jj = 0; jj < MAX_BSS_NUM ; jj++) {
		if (current_ev >= end_buf)
			break;
        pBSS = &(pMgmt->sBSSList[jj]);
        if (pBSS->bActive) {
		
		    memset(&iwe, 0, sizeof(iwe));
		    iwe.cmd = SIOCGIWAP;
		    iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
			memcpy(iwe.u.ap_addr.sa_data, pBSS->abyBSSID, WLAN_BSSID_LEN);
                           current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_ADDR_LEN);
                 
	             memset(&iwe, 0, sizeof(iwe));
                      iwe.cmd = SIOCGIWESSID;
                      pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
                       iwe.u.data.length = pItemSSID->len;
                       iwe.u.data.flags = 1;
                      current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID);
		
		    memset(&iwe, 0, sizeof(iwe));
		    iwe.cmd = SIOCGIWMODE;
            if (WLAN_GET_CAP_INFO_ESS(pBSS->wCapInfo)) {
		        iwe.u.mode = IW_MODE_INFRA;
            }
            else {
                iwe.u.mode = IW_MODE_ADHOC;
		    }
	        iwe.len = IW_EV_UINT_LEN;
                      current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe,  IW_EV_UINT_LEN);
           
            pSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abySuppRates;
            pExtSuppRates = (PWLAN_IE_SUPP_RATES)pBSS->abyExtSuppRates;
            memset(&iwe, 0, sizeof(iwe));
           	iwe.cmd = SIOCGIWFREQ;
           	iwe.u.freq.m = pBSS->uChannel;
           	iwe.u.freq.e = 0;
           	iwe.u.freq.i = 0;
                  current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
			{
			int f = (int)pBSS->uChannel - 1;
			if(f < 0)f = 0;
			iwe.u.freq.m = frequency_list[f] * 100000;
			iwe.u.freq.e = 1;
			}
                  current_ev = iwe_stream_add_event(info,current_ev,end_buf, &iwe, IW_EV_FREQ_LEN);
       		
            memset(&iwe, 0, sizeof(iwe));
	        iwe.cmd = IWEVQUAL;
	        RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
		    iwe.u.qual.level = ldBm;
	        iwe.u.qual.noise = 0;

			if(-ldBm<50){
				iwe.u.qual.qual = 100;
			}else  if(-ldBm > 90) {
				 iwe.u.qual.qual = 0;
			}else {
				iwe.u.qual.qual=(40-(-ldBm-50))*100/40;
			}
			iwe.u.qual.updated=7;

                 current_ev = iwe_stream_add_event(info,current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
       	
            memset(&iwe, 0, sizeof(iwe));
            iwe.cmd = SIOCGIWENCODE;
            iwe.u.data.length = 0;
            if (WLAN_GET_CAP_INFO_PRIVACY(pBSS->wCapInfo)) {
                iwe.u.data.flags =IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
            }else {
                iwe.u.data.flags = IW_ENCODE_DISABLED;
            }
            current_ev = iwe_stream_add_point(info,current_ev,end_buf, &iwe, pItemSSID->abySSID);

            memset(&iwe, 0, sizeof(iwe));
            iwe.cmd = SIOCGIWRATE;
           	iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
      		current_val = current_ev + IW_EV_LCP_LEN;

       		for (kk = 0 ; kk < 12 ; kk++) {
		        if (pSuppRates->abyRates[kk] == 0)
			        break;
		        
		        iwe.u.bitrate.value = ((pSuppRates->abyRates[kk] & 0x7f) * 500000);
                          current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
	        }
       		for (kk = 0 ; kk < 8 ; kk++) {
		        if (pExtSuppRates->abyRates[kk] == 0)
			        break;
		        
		        iwe.u.bitrate.value = ((pExtSuppRates->abyRates[kk] & 0x7f) * 500000);
                         current_val = iwe_stream_add_value(info,current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
	        }

	        if((current_val - current_ev) > IW_EV_LCP_LEN)
		        current_ev = current_val;

            memset(&iwe, 0, sizeof(iwe));
            iwe.cmd = IWEVCUSTOM;
            sprintf(buf, "bcn_int=%d", pBSS->wBeaconInterval);
            iwe.u.data.length = strlen(buf);
             current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, buf);

            if ((pBSS->wWPALen > 0) && (pBSS->wWPALen <= MAX_WPA_IE_LEN)) {
                memset(&iwe, 0, sizeof(iwe));
                iwe.cmd = IWEVGENIE;
                iwe.u.data.length = pBSS->wWPALen;
                current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byWPAIE);
            }

            if ((pBSS->wRSNLen > 0) && (pBSS->wRSNLen <= MAX_WPA_IE_LEN)) {
                memset(&iwe, 0, sizeof(iwe));
                iwe.cmd = IWEVGENIE;
                iwe.u.data.length = pBSS->wRSNLen;
                current_ev = iwe_stream_add_point(info,current_ev, end_buf, &iwe, pBSS->byRSNIE);
            }

        }
    }

	wrq->length = current_ev - extra;
	return 0;

}