int android_ioctl_siwpriv(struct net_device *dev,
              struct iw_request_info *__info,
              struct iw_point *data, char *__extra)
{
    char cmd[384]; /* assume that android command will not excess 384 */
    char buf[512];
    int len = sizeof(cmd)-1;
    AR_SOFTC_DEV_T *arPriv = (AR_SOFTC_DEV_T *)ar6k_priv(dev);
    AR_SOFTC_STA_T *arSta = &arPriv->arSta;

    if (!data->pointer) {
        return -EOPNOTSUPP;
    }
    if (data->length < len) {
        len = data->length;
    }
    if (copy_from_user(cmd, data->pointer, len)) {
        return -EIO;
    }
    cmd[len] = 0;

    if (strcasecmp(cmd, "RSSI")==0 || strcasecmp(cmd, "RSSI-APPROX") == 0) {
        int rssi = -200;
        struct iw_statistics *iwStats;
        struct iw_statistics* (*get_iwstats)(struct net_device *);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
        get_iwstats = dev->get_wireless_stats;
#else
        get_iwstats = dev->wireless_handlers->get_wireless_stats;
#endif
        if (get_iwstats && arPriv->arConnected) {
            iwStats = get_iwstats(dev);
            if (iwStats) {
                rssi = iwStats->qual.qual;          
                if (rssi == 255)
                    rssi = -200;
                else
                    rssi += (161 - 256);                
            }
        }
        len = snprintf(buf, data->length, "SSID rssi %d\n", rssi) + 1;
        return (copy_to_user(data->pointer, buf, len)==0) ? len : -1;
    } else if (strcasecmp(cmd, "LINKSPEED")==0) {
        /* We skip to use SIOCGIWRATE since Android always asked LINKSPEED just after RSSI*/
        unsigned int speed_mbps;
        if (arPriv->arConnected) {
            speed_mbps = arPriv->arTargetStats.tx_unicast_rate / 1000;
        } else {
            speed_mbps = 1;
        }
        len = snprintf(buf, data->length, "LinkSpeed %u\n", speed_mbps) + 1;
        return (copy_to_user(data->pointer, buf, len)==0) ? len : -1;
    } else if (memcmp(cmd, "CSCAN S\x01\x00\x00S\x00", 12)==0) {
        int iocmd = SIOCSIWSCAN - SIOCSIWCOMMIT;
        const iw_handler setScan = dev->wireless_handlers->standard[iocmd];
        A_INT32 home_dwell=0, pas_dwell=0, act_dwell=0;
        A_UCHAR ssid[IW_ESSID_MAX_SIZE+1] = { 0 };       
        A_INT32 ssid_len = 0, ie_len;
        A_UINT8 index = 1; /* reserve index 0 for wext */
        A_INT32 ch = 0;
        A_CHAR nprobe, scantype;
        struct iw_freq chList[IW_MAX_FREQUENCIES];
        A_UCHAR *scanBuf = (A_UCHAR*)(cmd + 12);
        A_UCHAR *scanEnd = (A_UCHAR*)(cmd + len);
        A_BOOL broadcastSsid = FALSE;

        while ( scanBuf < scanEnd ) {
            A_UCHAR *sp = scanBuf;
            switch (*scanBuf) {
            case 'S': /* SSID section */
                if (ssid_len > 0 && index < MAX_PROBED_SSID_INDEX) {
                    /* setup the last parsed ssid, reserve index 0 for wext */
                    if (wmi_probedSsid_cmd(arPriv->arWmi, index,
                                           SPECIFIC_SSID_FLAG, ssid_len, ssid) == A_OK) {
                        ++index;
                        if (arSta->scanSpecificSsid<index) {
                            arSta->scanSpecificSsid = index;
                        }
                    }
                }
                ie_len = ((scanBuf + 1) < scanEnd) ? ((A_INT32)*(scanBuf+1) + 1) : 0;
                if ((scanBuf+ie_len) < scanEnd ) {
                    ssid_len = *(scanBuf+1);
                    if (ssid_len == 0) {
                        broadcastSsid = TRUE;
                    } else {
                        A_MEMCPY(ssid, scanBuf+2, ssid_len);
                        ssid[ssid_len] = '\0';
                    }
                }
                scanBuf += 1 + ie_len;
                break;
            case 'C': /* Channel section */
                if (scanBuf+1 < scanEnd) {
                    int value = *(scanBuf+1);
                    if (value == 0) {
                        ch = 0; /* scan for all channels */
                    } else if (ch < IW_MAX_FREQUENCIES) {
                        if (value>1000) {
                            chList[ch].e = 1;
                            chList[ch].m = value * 100000;
                        } else {
                            chList[ch].e = 0;
                            chList[ch].m = value;
                        }
                        ++ch;
                    }
                }
                scanBuf += 2;
                break;
            case 'P': /* Passive dwell section */
                if (scanBuf+2 < scanEnd) {
                    pas_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'H': /* Home dwell section */
                if (scanBuf+2 < scanEnd) {
                    home_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'N': /* Number of probe section */
                if (scanBuf+1 < scanEnd) {
                    nprobe = *(scanBuf+1);
                }
                scanBuf += 2;
                break;
            case 'A': /* Active dwell section */
                if (scanBuf+2 < scanEnd) {
                    act_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'T': /* Scan active type section */
                if (scanBuf+1 < scanEnd) {
                    scantype = *(scanBuf+1);
                }
                scanBuf += 2;
                break;
            default:
                break;
            }
            if (sp == scanBuf) {
                return -1; /* parsing error */
            }
        }

        if (ssid_len>0) {
            A_UINT8 idx; /* Clean up the last specific scan items */
            for (idx=index; idx<arSta->scanSpecificSsid; ++idx) {
                wmi_probedSsid_cmd(arPriv->arWmi, idx, DISABLE_SSID_FLAG, 0, NULL);
            }
            arSta->scanSpecificSsid = index;
            /* 
             * There is no way to know when we need to send broadcast probe in current Android wpa_supplicant_6 
             * combo scan implemenation. Always force to sent it here uniti future Android version will set
             * the broadcast flags for combo scan.
             */
#if 0
            if (broadcastSsid)
#endif
            {
                /* setup the last index as broadcast SSID for combo scan */
                ++arSta->scanSpecificSsid;
                wmi_probedSsid_cmd(arPriv->arWmi, index, ANY_SSID_FLAG, 0, NULL);
            }
        }

        if (pas_dwell>0) {
            /* TODO: Should we change our passive dwell? There may be some impact for bt-coex */
        }

        if (home_dwell>0) {
            /* TODO: Should we adjust home_dwell? How to pass it to wext handler? */
        }

        if (setScan) {
            union iwreq_data miwr;
            struct iw_request_info minfo;
            struct iw_scan_req scanreq, *pScanReq = NULL;
            A_MEMZERO(&minfo, sizeof(minfo));
            A_MEMZERO(&miwr, sizeof(miwr));            
            A_MEMZERO(&scanreq, sizeof(scanreq));
            if (ssid_len > 0) {
                pScanReq = &scanreq;
                memcpy(scanreq.essid, ssid, ssid_len);
                scanreq.essid_len = ssid_len;
                miwr.data.flags |= IW_SCAN_THIS_ESSID;
            }
            if (ch > 0) {
                pScanReq = &scanreq;
                scanreq.num_channels = ch;
                memcpy(scanreq.channel_list, chList, ch * sizeof(chList[0]));
                miwr.data.flags |= IW_SCAN_THIS_FREQ;
            }
            if (pScanReq) {
                miwr.data.pointer = (__force void __user *)&scanreq;
                miwr.data.length = sizeof(scanreq);
            }
            minfo.cmd = SIOCSIWSCAN;
            return setScan(dev, &minfo, &miwr, (char*)pScanReq);
        }
        return -1;
    } else if (strcasecmp(cmd, "MACADDR")==0) {
        /* reply comes back in the form "Macaddr = XX:XX:XX:XX:XX:XX" where XX */
        A_UCHAR *mac = dev->dev_addr;
        len = snprintf(buf, data->length, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
                        mac[0], mac[1], mac[2],
                        mac[3], mac[4], mac[5]) + 1;
        return (copy_to_user(data->pointer, buf, len)==0) ? len : -1;
    } else if (strcasecmp(cmd, "SCAN-ACTIVE")==0) {
        return 0; /* unsupport function. Suppress the error */
    } else if (strcasecmp(cmd, "SCAN-PASSIVE")==0) {
        return 0; /* unsupport function. Suppress the error */
    } else if (strcasecmp(cmd, "START")==0 || strcasecmp(cmd, "STOP")==0) {
        struct ifreq ifr;
        char userBuf[16];
        int ex_arg = (strcasecmp(cmd, "START")==0) ? WLAN_ENABLED : WLAN_DISABLED;
        int ret;
        A_MEMZERO(userBuf, sizeof(userBuf));
        ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_SET_WLAN_STATE;
        ((int *)userBuf)[1] = ex_arg;
        ret = android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf);
        if (ret==0) {
            /* Send wireless event which need by android supplicant */
            union iwreq_data wrqu;
            A_MEMZERO(&wrqu, sizeof(wrqu));
            wrqu.data.length = strlen(cmd);
            wireless_send_event(dev, IWEVCUSTOM, &wrqu, cmd);
        }
        return ret;
    } else if (strncasecmp(cmd, "POWERMODE ", 10)==0) {
        int mode;
        if (sscanf(cmd, "%*s %d", &mode) == 1) {
            int iocmd = SIOCSIWPOWER - SIOCSIWCOMMIT;
            iw_handler setPower = dev->wireless_handlers->standard[iocmd];
            if (setPower) {
                union iwreq_data miwr;
                struct iw_request_info minfo;
                A_MEMZERO(&minfo, sizeof(minfo));
                A_MEMZERO(&miwr, sizeof(miwr));
                minfo.cmd = SIOCSIWPOWER;
                if (mode == 0 /* auto */)
                    miwr.power.disabled = 0;
                else if (mode == 1 /* active */)
                    miwr.power.disabled = 1;
                else
                    return -1;
                return setPower(dev, &minfo, &miwr, NULL);
            }
        }
        return -1;
    } else if (strcasecmp(cmd, "GETPOWER")==0) {
        struct ifreq ifr;
        int userBuf[2];
        A_MEMZERO(userBuf, sizeof(userBuf));
        ((int *)userBuf)[0] = AR6000_XIOCTRL_WMI_GET_POWER_MODE;
        if (android_do_ioctl_direct(dev, AR6000_IOCTL_EXTENDED, &ifr, userBuf)>=0) {
            WMI_POWER_MODE_CMD *getPowerMode = (WMI_POWER_MODE_CMD *)userBuf;
            len = snprintf(buf, data->length, "powermode = %u\n", 
                           (getPowerMode->powerMode==MAX_PERF_POWER) ? 1/*active*/ : 0/*auto*/) + 1;
            return (copy_to_user(data->pointer, buf, len)==0) ? len : -1;        
        }
        return -1;
    } else if (strncasecmp(cmd, "SETSUSPENDOPT ", 14)==0) {
        int enable;
        if (sscanf(cmd, "%*s %d", &enable)==1) {
            /* 
             * We set our suspend mode by wlan_config.h now. 
             * Should we follow Android command?? TODO
             */
            return 0;
        }
        return -1;
    } else if (strcasecmp(cmd, "SCAN-CHANNELS")==0) {
        // reply comes back in the form "Scan-Channels = X" where X is the number of channels        
        int iocmd = SIOCGIWRANGE - SIOCSIWCOMMIT;
        iw_handler getRange = dev->wireless_handlers->standard[iocmd];            
        if (getRange) {
            union iwreq_data miwr;
            struct iw_request_info minfo;
            struct iw_range range;
            A_MEMZERO(&minfo, sizeof(minfo));
            A_MEMZERO(&miwr, sizeof(miwr));
            A_MEMZERO(&range, sizeof(range));
            minfo.cmd = SIOCGIWRANGE;
            miwr.data.pointer = (__force void __user *) &range;
            miwr.data.length = sizeof(range);
            getRange(dev, &minfo, &miwr, (char*)&range);
        }
        if (arSta->arNumChannels!=-1) {
            len = snprintf(buf, data->length, "Scan-Channels = %d\n", arSta->arNumChannels) + 1;
            return (copy_to_user(data->pointer, buf, len)==0) ? len : -1;
        }
        return -1;
    } else if (strncasecmp(cmd, "SCAN-CHANNELS ", 14)==0 || 
               strncasecmp(cmd, "COUNTRY ", 8)==0) {
        /* 
         * Set the available channels with WMI_SET_CHANNELPARAMS cmd
         * However, the channels will be limited by the eeprom regulator domain
         * Try to use a regulator domain which will not limited the channels range.
         */
        int i;
        int chan = 0;
        A_UINT16 *clist;
        struct ifreq ifr; 
        char ioBuf[256];
        WMI_CHANNEL_PARAMS_CMD *chParamCmd = (WMI_CHANNEL_PARAMS_CMD *)ioBuf;
        if (strncasecmp(cmd, "COUNTRY ", 8)==0) {
            char *country = cmd + 8;
            if (strcasecmp(country, "US")==0) {
                chan = 11;
            } else if (strcasecmp(country, "JP")==0) {
                chan = 14;
            } else if (strcasecmp(country, "EU")==0) {
                chan = 13;
            }
        } else if (sscanf(cmd, "%*s %d", &chan) != 1) {
            return -1;
        }
        if ( (chan != 11) && (chan != 13) && (chan != 14)) {
            return -1;
        }
        if (arPriv->arNextMode == AP_NETWORK) {
            return -1;
        }
        A_MEMZERO(&ifr, sizeof(ifr));
        A_MEMZERO(ioBuf, sizeof(ioBuf));

        chParamCmd->phyMode = WMI_11G_MODE;
        clist = chParamCmd->channelList;
        chParamCmd->numChannels = chan;
        chParamCmd->scanParam = 1;        
        for (i = 0; i < chan; i++) {
            clist[i] = wlan_ieee2freq(i + 1);
        }
        
        return android_do_ioctl_direct(dev, AR6000_IOCTL_WMI_SET_CHANNELPARAMS, &ifr, ioBuf);
    } else if (strncasecmp(cmd, "BTCOEXMODE ", 11)==0) {
        int mode;
        if (sscanf(cmd, "%*s %d", &mode)==1) {
            /* 
            * Android disable BT-COEX when obtaining dhcp packet except there is headset is connected 
             * It enable the BT-COEX after dhcp process is finished
             * We ignore since we have our way to do bt-coex during dhcp obtaining.
             */
            switch (mode) {
            case 1: /* Disable*/
                break;
            case 0: /* Enable */
                /* fall through */
            case 2: /* Sense*/
                /* fall through */
            default:
                break;
            }
            return 0; /* ignore it */
        }
        return -1;
    } else if (strcasecmp(cmd, "BTCOEXSCAN-START")==0) {
        /* Android enable or disable Bluetooth coexistence scan mode. When this mode is on,
         * some of the low-level scan parameters used by the driver are changed to
         * reduce interference with A2DP streaming.
         */
        return 0; /* ignore it since we have btfilter  */
    } else if (strcasecmp(cmd, "BTCOEXSCAN-STOP")==0) {
        return 0; /* ignore it since we have btfilter  */
    } else if (strncasecmp(cmd, "RXFILTER-ADD ", 13)==0) {
        return 0; /* ignore it */
    } else if (strncasecmp(cmd, "RXFILTER-REMOVE ", 16)==0) {
        return 0; /* ignoret it */
    } else if (strcasecmp(cmd, "RXFILTER-START")==0 || strcasecmp(cmd, "RXFILTER-STOP")==0) {
        unsigned int flags = dev->flags;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
        int mc_count = dev->mc_count;   
#else
        int mc_count = netdev_mc_count(dev);
#endif
        if (strcasecmp(cmd, "RXFILTER-START")==0) {
            if (mc_count > 0 || (flags & IFF_MULTICAST) ) {
                flags &= ~IFF_MULTICAST;
            }
        } else {
            flags |= IFF_MULTICAST;
        }
        if (flags != dev->flags) {
            dev_change_flags(dev, flags);
        }
        return 0;
    }

    return -EOPNOTSUPP;
}
Exemple #2
0
void
CAR6KMini::WMIDisconnectIndication(A_UINT8 reason)
{
#ifdef NO_BCAST_PROBE_IN_CONNECT
    wmi_probedSsid_cmd((struct wmi_t *)m_pWMI, 0, ANY_SSID_FLAG, 0,NULL);
#endif
    do
    {
        //
        // Ignore pyxis specific reason during IEEE Mode
        //
        if (m_Connected)
        {
            if (reason == NO_NETWORK_AVAIL)
            {
                // remove the current associated bssid node
                wmi_free_node ((wmi_t *)m_pWMI, m_PeerBSSID);

                //
                // In case any other same SSID nodes are present
                // remove it, since those nodes also not available now
                //
                IterateNodeAndRemoveSSID (&m_SSID);

                SendWMIDisconnectCommand ();
            }

            // Flush any pending NDIS packets
            FlushNdisPacketTransmitQueue();

#ifdef OS_ROAM_MANAGEMENT
        if (FALSE == m_osRoamControl)
        {
#endif
        m_RSSIlevel = 0;
        if (m_Config.hostAssistedRoaming)
        {
            A_UNTIMEOUT(&m_rssiScanTimer);
        }
            NdisMIndicateStatus(m_MiniportAdapterHandle, NDIS_STATUS_MEDIA_DISCONNECT, 0, 0);
        NdisMIndicateStatusComplete(m_MiniportAdapterHandle);
#ifdef OS_ROAM_MANAGEMENT
        }
        else
        {
            A_UNTIMEOUT(&m_disconnectIndicationTimer);
            A_TIMEOUT_MS(&m_disconnectIndicationTimer, m_Config.discTimeout*1000, 0);
        }
#endif
        //
        // Reset Chanel and BSSID info
        //
        m_Connected         = FALSE;
        m_ChannelHint       = 0;
        m_ConnectedChannel  = 0;
        memset (m_PeerBSSID, 0, ETHERNET_MAC_ADDRESS_LENGTH);
    }

    if (m_bIsSwitchAPtoSTA)
    {
        m_bIsSwitchAPtoSTA = FALSE;
        NdisMIndicateStatus(m_MiniportAdapterHandle, NDIS_STATUS_MEDIA_DISCONNECT, 0, 0);
        NdisMIndicateStatusComplete(m_MiniportAdapterHandle);
       //     configTargetParams();
        m_WantToBeConnected = TRUE;
    }


        {
            //
            // no need to send WMIConnect when target reply disconnect
            // reason other than DISCONNECT_CMD
            //
            if (DISCONNECT_CMD == reason)
            {
                m_ConnectInProgress = FALSE;
                if (m_WantToBeConnected)
                {
                    SendWMIConnectCommand (&m_SSID);
                }
            }
        }

    } while (FALSE);

    NdisSetEvent (&m_SuspendEvent);
}
Exemple #3
0
static int ar6000_cscan(struct net_device *dev, struct iw_point *data, char *cmdbuf)
{
	char *ptr = cmdbuf;
	int iocmd = SIOCSIWSCAN - SIOCSIWCOMMIT;
	const iw_handler setScan = dev->wireless_handlers->standard[iocmd];
	A_INT32 home_dwell=0, pas_dwell=0, act_dwell=0;
	A_UCHAR ssid[IW_ESSID_MAX_SIZE+1] = { 0 };       
	A_INT32 ssid_len = 0, ie_len;
	A_UINT8 index = 1; /* reserve index 0 for wext */
	A_INT32 ch = 0,len=data->length ;
	A_CHAR nprobe, scantype;
	struct iw_freq chList[IW_MAX_FREQUENCIES];
	A_UCHAR *scanBuf = (A_UCHAR*)(ptr+ 12);
	A_UCHAR *scanEnd = (A_UCHAR*)(ptr + len);
	A_BOOL broadcastSsid = FALSE;
    AR_SOFTC_DEV_T *arPriv = (AR_SOFTC_DEV_T *)ar6k_priv(dev);
    AR_SOFTC_STA_T *arSta = &arPriv->arSta;

	while ( scanBuf < scanEnd ) 
	{
		A_UCHAR *sp = scanBuf;
		switch (*scanBuf) 
		{
			case 'S': /* SSID section */
				if (ssid_len > 0 && index < MAX_PROBED_SSID_INDEX) {
					/* setup the last parsed ssid, reserve index 0 for wext */
					if (wmi_probedSsid_cmd(arPriv->arWmi, index,
                                           SPECIFIC_SSID_FLAG, ssid_len, ssid) == A_OK) {
                        ++index;
                        if (arSta->scanSpecificSsid<index) {
                            arSta->scanSpecificSsid = index;
                        }
                    }
                }
                ie_len = ((scanBuf + 1) < scanEnd) ? ((A_INT32)*(scanBuf+1) + 1) : 0;
                if ((scanBuf+ie_len) < scanEnd ) {
                    ssid_len = *(scanBuf+1);
                    if (ssid_len == 0) {
                        broadcastSsid = TRUE;
                    } else {
                        A_MEMCPY(ssid, scanBuf+2, ssid_len);
                        ssid[ssid_len] = '\0';
                    }
                }
                scanBuf += 1 + ie_len;
                break;
            case 'C': /* Channel section */
                if (scanBuf+1 < scanEnd) {
                    int value = *(scanBuf+1);
                    if (value == 0) {
                        ch = 0; /* scan for all channels */
                    } else if (ch < IW_MAX_FREQUENCIES) {
                        if (value>1000) {
                            chList[ch].e = 1;
                            chList[ch].m = value * 100000;
                        } else {
                            chList[ch].e = 0;
                            chList[ch].m = value;
                        }
                        ++ch;
                    }
                }
                scanBuf += 2;
                break;
            case 'P': /* Passive dwell section */
                if (scanBuf+2 < scanEnd) {
                    pas_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'H': /* Home dwell section */
                if (scanBuf+2 < scanEnd) {
                    home_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'N': /* Number of probe section */
                if (scanBuf+1 < scanEnd) {
                    nprobe = *(scanBuf+1);
                }
                scanBuf += 2;
                break;
            case 'A': /* Active dwell section */
                if (scanBuf+2 < scanEnd) {
                    act_dwell = *(scanBuf+1) + (*(scanBuf+2) << 8);
                }
                scanBuf += 3;
                break;
            case 'T': /* Scan active type section */
                if (scanBuf+1 < scanEnd) {
                    scantype = *(scanBuf+1);
                }
                scanBuf += 2;
                break;
            default:
                break;
		} /* switch */
            if (sp == scanBuf) {
                return -1; /* parsing error */
            }
	}/* while */

	if (ssid_len>0) 
	{
		A_UINT8 idx; /* Clean up the last specific scan items */
		for (idx=index; idx<arSta->scanSpecificSsid; ++idx) {
			wmi_probedSsid_cmd(arPriv->arWmi, idx, DISABLE_SSID_FLAG, 0, NULL);
		}
		arSta->scanSpecificSsid = index;
		/* 
		* There is no way to know when we need to send broadcast probe in current Android wpa_supplicant_6 
		* combo scan implemenation. Always force to sent it here uniti future Android version will set
		* the broadcast flags for combo scan.
		*/
#if 0
		if (broadcastSsid)
#endif
		{
			/* setup the last index as broadcast SSID for combo scan */
			++arSta->scanSpecificSsid;
			wmi_probedSsid_cmd(arPriv->arWmi, index, ANY_SSID_FLAG, 0, NULL);
		}
	}

	if (pas_dwell>0) {
		/* TODO: Should we change our passive dwell? There may be some impact for bt-coex */
	}

	if (home_dwell>0) {
		/* TODO: Should we adjust home_dwell? How to pass it to wext handler? */
	}

	if (setScan) {
		union iwreq_data miwr;
		struct iw_request_info minfo;
		struct iw_scan_req scanreq, *pScanReq = NULL;

		A_MEMZERO(&minfo, sizeof(minfo));
		A_MEMZERO(&miwr, sizeof(miwr));            
		A_MEMZERO(&scanreq, sizeof(scanreq));

		if (ssid_len > 0) {
			pScanReq = &scanreq;
			memcpy(scanreq.essid, ssid, ssid_len);
			scanreq.essid_len = ssid_len;
			miwr.data.flags |= IW_SCAN_THIS_ESSID;
		}
		if (ch > 0) {
			pScanReq = &scanreq;
			scanreq.num_channels = ch;
			memcpy(scanreq.channel_list, chList, ch * sizeof(chList[0]));
			miwr.data.flags |= IW_SCAN_THIS_FREQ;
		}
		if (pScanReq) {
			miwr.data.pointer = (__force void __user *)&scanreq;
			miwr.data.length = sizeof(scanreq);
		}
		minfo.cmd = SIOCSIWSCAN;
		return setScan(dev, &minfo, &miwr, (char*)pScanReq);
	}
	return -1;
}
Exemple #4
0
void
CAR6KMini::WMIConnectIndication(
    IN USHORT Channel,
    IN PBYTE  PeerBSSID,
    IN USHORT listenInterval,
    IN BYTE   assocReqLen,
    IN BYTE   assocRespLen,
    IN PBYTE  assocInfo,
    IN BYTE   beaconIeLen,
    IN USHORT beaconInterval,
    NETWORK_TYPE networkType)
{
    BYTE        len = 0;
    int         i = 0;
    PBYTE       pAssocReq;
    PBYTE       pAssocReqEnd;
    PBYTE       pBeaconIE;
    BYTE        byKeyType = 0;
#ifdef OS_ROAM_MANAGEMENT
    A_UNTIMEOUT(&m_disconnectIndicationTimer);
#endif
#ifdef NO_BCAST_PROBE_IN_CONNECT
    wmi_probedSsid_cmd((struct wmi_t *)m_pWMI, 0, ANY_SSID_FLAG, 0,NULL);
#endif


    memcpy(m_PeerBSSID, PeerBSSID, ETHERNET_MAC_ADDRESS_LENGTH);
    m_ConnectedChannel      = Channel;
    m_ConnectInProgress     = FALSE;
    m_AssocReqLen           = assocReqLen;
    m_AssocRespLen          = assocRespLen;
    m_BeaconIeLen           = beaconIeLen;
    m_BeaconInterval        = beaconInterval;
    m_WantToBeConnected     = FALSE;

    if (m_pAssocInfo != NULL) {
        A_FREE(m_pAssocInfo);
    }

    m_pAssocInfo = (PBYTE)A_MALLOC(m_AssocReqLen + m_AssocRespLen + m_BeaconIeLen);

    if (m_pAssocInfo)
    {
        memcpy(m_pAssocInfo, assocInfo, m_AssocReqLen + m_AssocRespLen + m_BeaconIeLen);

        //Get network type in use
        if (m_ConnectedChannel >= 2412 && m_ConnectedChannel <= 2484) {
            PBYTE pAssocRsp = m_pAssocInfo + m_BeaconIeLen + m_AssocReqLen;
            PBYTE pAssocRspEnd = pAssocRsp + m_AssocRespLen;

            m_NetworkTypeInUse = Ndis802_11DS;

            //Skip capability, status code and assoc. ID
            pAssocRsp += 6;
            if ((pAssocRsp + 2) < pAssocRspEnd && IEEE80211_ELEMID_RATES == pAssocRsp[0]) {
                pAssocRsp += (pAssocRsp[1] + 2);
                if ((pAssocRsp + 2) < pAssocRspEnd && IEEE80211_ELEMID_XRATES == pAssocRsp[0]) {
                    m_NetworkTypeInUse = Ndis802_11OFDM24;
                }
            }
        }
        else {
            m_NetworkTypeInUse = Ndis802_11OFDM5;
        }

        // Update the group wise crypto type from the ie info
    #define RSN_MULTICAST_CIPHER_OFFSET 7
    #define WPA_MULTICAST_CIPHER_OFFSET 11
        pBeaconIE = m_pAssocInfo;
        if (m_BeaconIeLen) {
            if ((m_AuthenticationMode == Ndis802_11AuthModeWPA2) ||
                (m_AuthenticationMode == Ndis802_11AuthModeWPA2PSK))
            {
                if (m_BeaconIeLen <= RSN_MULTICAST_CIPHER_OFFSET) {
                    // Default to AES if cipher suite not present
                    m_GrpwiseCryptoType = AES_CRYPT;
                } else {
                    byKeyType = *(pBeaconIE + RSN_MULTICAST_CIPHER_OFFSET);
                    switch (byKeyType)
                    {
                        case RSN_CSE_WEP40:
                        case RSN_CSE_WEP104:
                            m_GrpwiseCryptoType = WEP_CRYPT;
                            break;
                        case RSN_CSE_TKIP:
                            m_GrpwiseCryptoType = TKIP_CRYPT;
                            break;
                        case RSN_CSE_CCMP:
                            m_GrpwiseCryptoType = AES_CRYPT;
                            break;
                    }
                }
            } else
                if ((m_AuthenticationMode == Ndis802_11AuthModeWPA) ||
                    (m_AuthenticationMode == Ndis802_11AuthModeWPAPSK))
            {
                if (m_BeaconIeLen <= WPA_MULTICAST_CIPHER_OFFSET) {
                    // Default to TKIP if cipher suite not present
                    m_GrpwiseCryptoType = TKIP_CRYPT;
                } else {
                    byKeyType = *(pBeaconIE + WPA_MULTICAST_CIPHER_OFFSET);
                    switch (byKeyType)
                    {
                        case WPA_CSE_WEP40:
                        case WPA_CSE_WEP104:
                            m_GrpwiseCryptoType = WEP_CRYPT;
                            break;
                        case WPA_CSE_TKIP:
                            m_GrpwiseCryptoType = TKIP_CRYPT;
                            break;
                        case WPA_CSE_CCMP:
                            m_GrpwiseCryptoType = AES_CRYPT;
                            break;
                    }
                }
            }
        }

        // Get supported basic rates
        pAssocReq = m_pAssocInfo + m_BeaconIeLen;
        pAssocReqEnd = pAssocReq + m_AssocReqLen;

        // skip capability and listen interval
        pAssocReq += 4;

        if (((pAssocReq + 2) < pAssocReqEnd) &&
            (IEEE80211_ELEMID_SSID == pAssocReq[0]))
        {
            // Skip SSID
            pAssocReq += (pAssocReq[1] + 2);
            if ((pAssocReq + 2) < pAssocReqEnd &&
                IEEE80211_ELEMID_RATES == pAssocReq[0] &&
                (pAssocReq + pAssocReq[1] + 2) <= pAssocReqEnd)
            {
                // Get rates
                memset (m_pSupportedRates, 0, sizeof(NDIS_802_11_RATES));
                memcpy(m_pSupportedRates, &pAssocReq[2],
                      (pAssocReq[1] < sizeof(NDIS_802_11_RATES)) ? pAssocReq[1] : sizeof(NDIS_802_11_RATES));
            }
        }

    }

#ifdef OS_ROAM_MANAGEMENT
    m_RateInfo.TxDataFrames = 0;
    m_RateInfo.RxDataFrames = 0;
#endif

    // Indicate MEDIA_CONNECT to Ndis

    ConnectIndicationPostProc ();
    if (networkType == INFRA_NETWORK){
        m_Connected         = TRUE;
        m_ConnectInProgress = FALSE;
        NdisMIndicateStatus (m_MiniportAdapterHandle, NDIS_STATUS_MEDIA_CONNECT, 0, 0);
        NdisMIndicateStatusComplete (m_MiniportAdapterHandle);
    }else{
        m_Connected = FALSE;
    }
    m_RSSIlevel = 0;
    if (m_Config.hostAssistedRoaming)
    {
        A_UNTIMEOUT(&m_rssiScanTimer);
        A_TIMEOUT_MS(&m_rssiScanTimer, 1000, 0);
    }

    return;
}