Пример #1
0
static wifi_error get_firmware_bus_max_size_supported(
                                                wifi_interface_handle iface)
{
    int ret = 0;
    interface_info *iinfo = getIfaceInfo(iface);
    wifi_handle handle = getWifiHandle(iface);
    hal_info *info = (hal_info *)handle;

    WifihalGeneric busSizeSupported(handle, 0,
                                    OUI_QCA,
                                    QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE);

    /* create the message */
    ret = busSizeSupported.create();
    if (ret < 0)
        goto cleanup;

    ret = busSizeSupported.set_iface_id(iinfo->name);
    if (ret < 0)
        goto cleanup;

    ret = busSizeSupported.requestResponse();
    if (ret != 0) {
        ALOGE("%s: requestResponse Error:%d", __FUNCTION__, ret);
        goto cleanup;
    }
    info->firmware_bus_max_size = busSizeSupported.getBusSize();

cleanup:
    return mapErrorKernelToWifiHAL(ret);
}
Пример #2
0
static wifi_error acquire_supported_features(wifi_interface_handle iface,
        feature_set *set)
{
    int ret = 0;
    interface_info *iinfo = getIfaceInfo(iface);
    wifi_handle handle = getWifiHandle(iface);
    *set = 0;

    WifihalGeneric supportedFeatures(handle, 0,
            OUI_QCA,
            QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES);

    /* create the message */
    ret = supportedFeatures.create();
    if (ret < 0)
        goto cleanup;

    ret = supportedFeatures.set_iface_id(iinfo->name);
    if (ret < 0)
        goto cleanup;

    ret = supportedFeatures.requestResponse();
    if (ret != 0) {
        ALOGE("%s: requestResponse Error:%d",__func__, ret);
        goto cleanup;
    }

    supportedFeatures.getResponseparams(set);

cleanup:
    return mapErrorKernelToWifiHAL(ret);
}
//Implementation of the functions exposed in linklayer.h
wifi_error wifi_set_link_stats(wifi_interface_handle iface,
                               wifi_link_layer_params params)
{
    int ret = 0;
    LLStatsCommand *LLCommand;
    struct nlattr *nl_data;
    interface_info *iinfo = getIfaceInfo(iface);
    wifi_handle handle = getWifiHandle(iface);
    LLCommand = LLStatsCommand::instance(handle);
    if (LLCommand == NULL) {
        ALOGE("%s: Error LLStatsCommand NULL", __func__);
        return WIFI_ERROR_UNKNOWN;
    }
    LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_SET);

    /* create the message */
    ret = LLCommand->create();
    if (ret < 0)
        goto cleanup;

    ret = LLCommand->set_iface_id(iinfo->name);
    if (ret < 0)
        goto cleanup;

    /*add the attributes*/
    nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    if (!nl_data)
        goto cleanup;
    /**/
    ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_MPDU_SIZE_THRESHOLD,
                                  params.mpdu_size_threshold);
    if (ret < 0)
        goto cleanup;
    /**/
    ret = LLCommand->put_u32(
                QCA_WLAN_VENDOR_ATTR_LL_STATS_SET_CONFIG_AGGRESSIVE_STATS_GATHERING,
                params.aggressive_statistics_gathering);
    if (ret < 0)
        goto cleanup;
    LLCommand->attr_end(nl_data);

    ret = LLCommand->requestResponse();
    if (ret != 0) {
        ALOGE("%s: requestResponse Error:%d",__func__, ret);
    }

cleanup:
    return (wifi_error)ret;
}
Пример #4
0
/*
 * Function: CreateInterfaceEntry
 *
 * Arguments:	dev - A pointer to the device name
 *		regLifetime - The maximum registration lifetime that
 *			are willing to accept.
 *		advertiseOnBcast - Whether we will advertise on the
 *			broadcast address.
 *		minInterval - The minimum interval between adv.
 *		maxInterval - The maximum interval between adv.
 *		advLifetime - The maximum advertisement lifetime
 *			lifetime that we will advertise on this
 *			interface.
 *		advSeqNum - The sequence number that we will
 *			initially advertise.
 *		servicesFlags - The flags that we will advertise
 *			on the interface.
 *		prefixFlags - determines whether we will advertise
 *			the prefix length extension.
 *		reverseTunnelAllowed - are we going to allow MN's to
 *			request the reverse tunnel, and thereby send
 *			FA_REVERSE_TUNNEL_UNAVAILABLE errors to MN's
 *			requesting a reverse tunnel?  Note, this is set to
 *			RT_NONE, RT_FA, RT_HA, or RT_BOTH depending on which
 *			of our agents is allowing the reverse tunnel.
 *		reverseTunnelRequired - are we going to require MN's to
 *			request the reverse tunnel, and thereby send
 *			FA_REVERSE_TUNNEL_REQUIRED errors to MN's not
 *			requesting a reverse tunnel?  Note, this is set to
 *			RT_NONE, RT_FA, RT_HA, or RT_BOTH depending on which
 *			of our agents is requiring the reverse tunnel.
 *		advInterval - Advertisement interval for this interface
 *
 * Description: This function will create an interface entry,
 *		and will add it to the hash table. We will
 *		directly retrieve the interface's IP address and
 *		MAC address.
 *
 * Returns: int, 0 if successful.
 *
 * Comment:	This function takes too many arguments. If this function
 *		ever needs a major change, passing a structure with all
 *		arguments should be considered.
 *
 */
int
CreateInterfaceEntry(char *dev, int regLifetime, boolean_t advertiseOnBcast,
    int minInterval, int maxInterval, int advLifetime, uint16_t advSeqNum,
    int servicesFlags, boolean_t prefixFlags, uint8_t reverseTunnelAllowed,
    uint8_t reverseTunnelRequired, boolean_t advLimitUnsolicited, uint8_t
    advInitCount, uint32_t advInterval, boolean_t isDynamic)
{
	MaAdvConfigEntry *entry;
	char *cp;

	/* If a virtual network interface is specified, warn the user */
	if (dev != NULL) {
		if ((strncmp(dev, VNI, VNISTRLEN) == 0)) {
			cp = dev + VNISTRLEN;
			cp += strspn(cp, "0123456789");
			if (*cp == '\0' || *cp == ':' || *cp == '*')
				syslog(LOG_WARNING, "%s specified. vni is a"
				    " virtual interface that does not transmit"
				    " or receive packets. See vni(7D)", dev);
		}
	}

	/* Let's check for dynamic interface entry */
	if (strchr(dev, '*') == NULL) {
		entry = (MaAdvConfigEntry *) calloc(1,
		    sizeof (MaAdvConfigEntry));
		if (entry == NULL) {
			syslog(LOG_CRIT, "FATAL: Unable to allocate "
			    "AdvConfigEntry");
			return (-2);
		}
	} else {
		int	len;
		DynamicIfaceTypeEntry	*dyn_entry;
		DynamicIfaceTypeEntry	*save_entry;

		/*
		 * Since devicename contains '*', it must be an entry
		 * for dynamic interface.For dynamic interface entry
		 * in the config file, we do not create entry in the
		 * MaAdvConfigEntry[], rather we keep a linked list
		 * of dynamic interface types. For each type of dynamic
		 * interface entry, the attributes will be common and
		 * saved in DynamicIfaceTypeEntry data structure.
		 * When mipagent detects one new interface that matches
		 * with the same type and that is not an exisisting one
		 * that went through down-up cycle, then it creates a new
		 * entry and attaches to the MaAdvConfigEntry list
		 */
		len = strlen(dev);
		if (len > 0 && dev[len - 1] != '*') {
			syslog(LOG_ERR,
			    "Invalid dynamic interface %s in mipagent.conf",
			    dev);
			return (-1);
		}
		/* Replace '*' with null character */
		dev[len -1] = '\0';
		mipverbose(("CreateInterfaceEntry: dynamic device %s\n",
		    dev));


		if (dynamicIfaceHead == NULL) {
			dynamicIfaceHead = (DynamicIfaceTypeEntry *) calloc(1,
			    sizeof (DynamicIfaceTypeEntry));
			dyn_entry = dynamicIfaceHead;
		} else {

			/* search if this type exists already */
			dyn_entry = dynamicIfaceHead;
			while (dyn_entry != NULL) {
				if (strcmp(dyn_entry->dynamicIfcetype, dev)
				    == 0) {
					mipverbose(("CreateInterfaceEntry:"
					    " Dynamic Entry already exists"
					    " %s\n", dev));
					return (0);
				}
				save_entry = dyn_entry;
				dyn_entry = dyn_entry->next;
			}

			dyn_entry = (DynamicIfaceTypeEntry *) calloc(1,
			    sizeof (DynamicIfaceTypeEntry));
			if (dyn_entry != NULL) {
				/* Link to the dynamicEntry list */
				save_entry->next = dyn_entry;
			}
		}

		/* Fill in the structure with the parameter values */
		(void) strncpy(dyn_entry->dynamicIfcetype, dev, LIFNAMSIZ);
		dyn_entry->AdvLimitUnsolicited = advLimitUnsolicited;
		dyn_entry->AdvInitCount = advInitCount;
		dyn_entry->AdvInterval = advInterval;
		dyn_entry->AdvServiceflag = servicesFlags;
		dyn_entry->AdvPrefixflag = prefixFlags;
		dyn_entry->RevtunReqd = reverseTunnelRequired;
		dyn_entry->RevtunAllowed = reverseTunnelAllowed;
		dyn_entry->RegLifetime = regLifetime;
		dyn_entry->AdvLifetime = advLifetime;
		dyn_entry->advertiseOnBcast = advertiseOnBcast;
		dyn_entry->next = NULL;

		/* Set the global variable DynamicInterface */
		DynamicInterface = _B_TRUE;
		return (0);
	} /* else dynamic entry */

	/* Now add our interface values */
	(void) strncpy(entry->maIfaceName, dev, (LIFNAMSIZ -1));

	/*
	 * Simplify the configuration effort, read IP address, netmask
	 * and hardware address directly from the interface.
	 */
	if (getIfaceInfo(entry->maIfaceName, &entry->maIfaceAddr,
	    &entry->maIfaceNetmask, &entry->maIfaceFlags,
	    &entry->maIfindex)) {
		free(entry);
		syslog(LOG_ERR, "Unable to get interface information: %m");
		return (-1);
	}

	/*
	 * Save the first address usable for registering with the
	 * SNMP master.
	 */
	if (subagent_addr != 0)
		subagent_addr = entry->maIfaceAddr;

	/*
	 * Don't attempt to get the hardware address if it's a point-to-point
	 * interface.
	 */
	if ((entry->maIfaceFlags & IFF_POINTOPOINT) == 0) {
		if (getEthernetAddr(entry->maIfaceName, entry->maIfaceHWaddr)) {
			syslog(LOG_ERR, "Unable to get interface address "
			    "information on %s (%s)", dev, strerror(errno));
			mipverbose(("Unable to get interface address "
			    "information on %s (%s)\n", dev, strerror(errno)));
			free(entry);
			return (-1);
		}
	}

	entry->maAdvMaxRegLifetime = regLifetime;

	/*
	 * TODO: Under Solaris, pkts for LINK_BCAST_ADDR seem to
	 * be sent on all of a host's interfaces. Don't know if this
	 * can be controlled using some options similar to
	 * IP_MULTICAST_IF.
	 */
	if (advertiseOnBcast == 1) {
		entry->maAdvAddr = inet_addr(LINK_BCAST_ADDR);
	} else {
		entry->maAdvAddr = inet_addr(LINK_MCAST_ADV_ADDR);
	}

	entry->maAdvMaxInterval = maxInterval;
	entry->maAdvMinInterval = minInterval;
	entry->maAdvMaxAdvLifetime = advLifetime;
	entry->maAdvSeqNum = advSeqNum;
	entry->maAdvServiceFlags = (char)servicesFlags;
	entry->maAdvPrefixLenInclusion = prefixFlags;
	entry->maReverseTunnelAllowed = reverseTunnelAllowed;
	entry->maReverseTunnelRequired = reverseTunnelRequired;
	entry->maAdvLimitUnsolicited = advLimitUnsolicited;
	if (advLimitUnsolicited == _B_FALSE)
		entry->maAdvInitCount = 1;
	else
		entry->maAdvInitCount = advInitCount;
	entry->maAdvInterval = advInterval;
	/* Set maNextAdvTime in getAndDispatchNetwork */
	entry->maNextAdvTime = LONG_MAX;
	/* The follwoing is always set false in this routine */
	entry->maAdvDynamicInterface = isDynamic;

	if (rwlock_init(&entry->maIfaceNodeLock, USYNC_THREAD, NULL)) {
		syslog(LOG_ERR, "Unable to initialize read/write lock");
		free(entry);
		return (NULL);
	}

	/*
	 * Ok, this is just a temp hack, but we need to save the
	 * local address of the interface. Otherwise we will need to
	 * configure the home agent for each Mobile Node, which is
	 * just too much config for everybody. Given that we really
	 * only work with one interface, this is not a big deal, but
	 * this DOES need to be cleaned up.
	 */
	haAddr = entry->maIfaceAddr;

	/*
	 * We do not request that the node be locked in this case since
	 * we do not need the pointer to be returned. We are just calling
	 * and ensuring that a pointer was in fact returned.
	 */
	if (linkHashTableEntryUint(&maAdvConfigHash, entry->maIfaceAddr, entry,
	    LOCK_NONE)) {
		syslog(LOG_ERR, "Unable to add interface entry to hash table");
		(void) rwlock_destroy(&entry->maIfaceNodeLock);
		free(entry);
		return (-1);
	}

	return (0);
}
//Implementation of the functions exposed in LLStats.h
wifi_error wifi_get_link_stats(wifi_request_id id,
                               wifi_interface_handle iface,
                               wifi_stats_result_handler handler)
{
    int ret = 0;
    LLStatsCommand *LLCommand;
    struct nlattr *nl_data;
    interface_info *iinfo = getIfaceInfo(iface);
    wifi_handle handle = getWifiHandle(iface);
    pthread_t tid;

    LLCommand = LLStatsCommand::instance(handle);
    if (LLCommand == NULL) {
        ALOGE("%s: Error LLStatsCommand NULL", __func__);
        return WIFI_ERROR_UNKNOWN;
    }
    LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_GET);

    LLCommand->initGetContext(id);

    LLStatsCallbackHandler callbackHandler =
    {
        .on_link_stats_results = handler.on_link_stats_results
    };

    /* create the message */
    ret = LLCommand->create();
    if (ret < 0)
        goto cleanup;

    ret = LLCommand->set_iface_id(iinfo->name);
    if (ret < 0)
        goto cleanup;
    /*add the attributes*/
    nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    if (!nl_data)
        goto cleanup;
    ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_ID,
                                  id);
    if (ret < 0)
        goto cleanup;
    ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_GET_CONFIG_REQ_MASK,
                                  7);
    if (ret < 0)
        goto cleanup;

    /**/
    LLCommand->attr_end(nl_data);

    ret = LLCommand->requestResponse();
    if (ret != 0) {
        ALOGE("%s: requestResponse Error:%d",__func__, ret);
    }
    if (ret < 0)
        goto cleanup;

    ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
    if (ret < 0)
        goto cleanup;
    ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
    if (ret < 0)
        goto cleanup;
    ret = LLCommand->setCallbackHandler(callbackHandler, QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
    if (ret < 0)
        goto cleanup;
cleanup:
    return (wifi_error)ret;
}


//Implementation of the functions exposed in LLStats.h
wifi_error wifi_clear_link_stats(wifi_interface_handle iface,
                                 u32 stats_clear_req_mask,
                                 u32 *stats_clear_rsp_mask,
                                 u8 stop_req, u8 *stop_rsp)
{
    int ret = 0;
    LLStatsCommand *LLCommand;
    struct nlattr *nl_data;
    interface_info *iinfo = getIfaceInfo(iface);
    wifi_handle handle = getWifiHandle(iface);

    LLCommand = LLStatsCommand::instance(handle);
    if (LLCommand == NULL) {
        ALOGE("%s: Error LLStatsCommand NULL", __func__);
        return WIFI_ERROR_UNKNOWN;
    }
    LLCommand->setSubCmd(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_CLR);

    /* create the message */
    ret = LLCommand->create();
    if (ret < 0)
        goto cleanup;

    ret = LLCommand->set_iface_id(iinfo->name);
    if (ret < 0)
        goto cleanup;
    /*add the attributes*/
    nl_data = LLCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
    if (!nl_data)
        goto cleanup;
    /**/
    ret = LLCommand->put_u32(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_REQ_MASK,
                                  stats_clear_req_mask);
    if (ret < 0)
        goto cleanup;
    /**/
    ret = LLCommand->put_u8(QCA_WLAN_VENDOR_ATTR_LL_STATS_CLR_CONFIG_STOP_REQ,
                                   stop_req);
    if (ret < 0)
        goto cleanup;
    LLCommand->attr_end(nl_data);

    ret = LLCommand->requestResponse();
    if (ret != 0) {
        ALOGE("%s: requestResponse Error:%d",__func__, ret);
    }

    LLCommand->getClearRspParams(stats_clear_rsp_mask, stop_rsp);

cleanup:
    LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_RADIO_RESULTS);
    LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_IFACE_RESULTS);
    LLCommand->unregisterHandler(QCA_NL80211_VENDOR_SUBCMD_LL_STATS_PEERS_RESULTS);
    delete LLCommand;
    return (wifi_error)ret;
}