Пример #1
0
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
{
	struct sk_buff *reply;
	struct wl_priv *wl;
	dhd_pub_t *dhd;
	dhd_ioctl_t *ioc = data;
	int err = 0;

	WL_TRACE(("entry: cmd = %d\n", ioc->cmd));
	wl = wiphy_priv(wiphy);
	dhd = wl->pub;

	DHD_OS_WAKE_LOCK(dhd);

	/* send to dongle only if we are not waiting for reload already */
	if (dhd->hang_was_sent) {
		WL_ERR(("HANG was sent up earlier\n"));
		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
		DHD_OS_WAKE_UNLOCK(dhd);
		return OSL_ERROR(BCME_DONGLE_DOWN);
	}

	/* currently there is only one wiphy for ifidx 0 */
	err = dhd_ioctl_process(dhd, 0, ioc);
	if (err)
		goto done;

	/* response data is in ioc->buf so return ioc here */
	reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc));
	nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc);
	err = cfg80211_testmode_reply(reply);
done:
	DHD_OS_WAKE_UNLOCK(dhd);
	return err;
}
Пример #2
0
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
{
	struct sk_buff *reply;
	struct wl_priv *wl;
	dhd_pub_t *dhd;
	dhd_ioctl_t *ioc = data;
	int err = 0;

	WL_TRACE(("entry: cmd = %d\n", ioc->cmd));
	wl = wiphy_priv(wiphy);
	dhd = wl->pub;

	DHD_OS_WAKE_LOCK(dhd);

	
	if (dhd->hang_was_sent) {
		WL_ERR(("%s: HANG was sent up earlier\n", __FUNCTION__));
		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
		DHD_OS_WAKE_UNLOCK(dhd);
		return OSL_ERROR(BCME_DONGLE_DOWN);
	}

	
	err = dhd_ioctl_process(dhd, 0, ioc);
	if (err)
		goto done;

	
	reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc));
	nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc);
	err = cfg80211_testmode_reply(reply);
done:
	DHD_OS_WAKE_UNLOCK(dhd);
	return err;
}
static int dhd_cfgvendor_priv_string_handler(struct wiphy *wiphy,
	struct wireless_dev *wdev, const void  *data, int len)
{
	const struct bcm_nlmsg_hdr *nlioc = data;
	struct net_device *ndev = NULL;
	struct bcm_cfg80211 *cfg;
	struct sk_buff *reply;
	void *buf = NULL, *cur;
	dhd_pub_t *dhd;
	dhd_ioctl_t ioc = { 0 };
	int ret = 0, ret_len, payload, msglen;
	int maxmsglen = PAGE_SIZE - 0x100;
	int8 index;

	WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));

	cfg = wiphy_priv(wiphy);
	dhd = cfg->pub;

	DHD_OS_WAKE_LOCK(dhd);

	/* send to dongle only if we are not waiting for reload already */
	if (dhd->hang_was_sent) {
		WL_ERR(("HANG was sent up earlier\n"));
		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
		DHD_OS_WAKE_UNLOCK(dhd);
		return OSL_ERROR(BCME_DONGLE_DOWN);
	}

	len -= sizeof(struct bcm_nlmsg_hdr);
	ret_len = nlioc->len;
	if (ret_len > 0 || len > 0) {
		if (len > DHD_IOCTL_MAXLEN) {
			WL_ERR(("oversize input buffer %d\n", len));
			len = DHD_IOCTL_MAXLEN;
		}
		if (ret_len > DHD_IOCTL_MAXLEN) {
			WL_ERR(("oversize return buffer %d\n", ret_len));
			ret_len = DHD_IOCTL_MAXLEN;
		}
		payload = max(ret_len, len) + 1;
		buf = vzalloc(payload);
		if (!buf) {
			DHD_OS_WAKE_UNLOCK(dhd);
			return -ENOMEM;
		}
		memcpy(buf, (void *)nlioc + nlioc->offset, len);
		*(char *)(buf + len) = '\0';
	}

	ndev = wdev_to_wlc_ndev(wdev, cfg);
	index = dhd_net2idx(dhd->info, ndev);
	if (index == DHD_BAD_IF) {
		WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
		ret = BCME_ERROR;
		goto done;
	}

	ioc.cmd = nlioc->cmd;
	ioc.len = nlioc->len;
	ioc.set = nlioc->set;
	ioc.driver = nlioc->magic;
	ret = dhd_ioctl_process(dhd, index, &ioc, buf);
	if (ret) {
		WL_TRACE(("dhd_ioctl_process return err %d\n", ret));
		ret = OSL_ERROR(ret);
		goto done;
	}

	cur = buf;
	while (ret_len > 0) {
		msglen = nlioc->len > maxmsglen ? maxmsglen : ret_len;
		ret_len -= msglen;
		payload = msglen + sizeof(msglen);
		reply = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, payload);
		if (!reply) {
			WL_ERR(("Failed to allocate reply msg\n"));
			ret = -ENOMEM;
			break;
		}

		if (nla_put(reply, BCM_NLATTR_DATA, msglen, cur) ||
			nla_put_u16(reply, BCM_NLATTR_LEN, msglen)) {
			kfree_skb(reply);
			ret = -ENOBUFS;
			break;
		}

		ret = cfg80211_vendor_cmd_reply(reply);
		if (ret) {
			WL_ERR(("testmode reply failed:%d\n", ret));
			break;
		}
		cur += msglen;
	}

done:
	vfree(buf);
	DHD_OS_WAKE_UNLOCK(dhd);
	return ret;
}
Пример #4
0
int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
{
	struct sk_buff *reply;
	struct bcm_cfg80211 *cfg;
	dhd_pub_t *dhd;
	struct bcm_nlmsg_hdr *nlioc = data;
	dhd_ioctl_t ioc = { 0 };
	int err = 0;
	void *buf = NULL, *cur;
	u16 buflen;
	u16 maxmsglen = PAGE_SIZE - 0x100;
	bool newbuf = false;
	int8 index = 0;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
	struct net_device *ndev = NULL;
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */

	WL_TRACE(("entry: cmd = %d\n", nlioc->cmd));
	cfg = wiphy_priv(wiphy);
	dhd = cfg->pub;

	DHD_OS_WAKE_LOCK(dhd);

	/* send to dongle only if we are not waiting for reload already */
	if (dhd->hang_was_sent) {
		WL_ERR(("HANG was sent up earlier\n"));
		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS);
		DHD_OS_WAKE_UNLOCK(dhd);
		return OSL_ERROR(BCME_DONGLE_DOWN);
	}

	len -= sizeof(struct bcm_nlmsg_hdr);

	if (nlioc->len > 0) {
		if (nlioc->len <= len) {
			buf = (void *)nlioc + nlioc->offset;
			*(char *)(buf + nlioc->len) = '\0';
		} else {
			if (nlioc->len > DHD_IOCTL_MAXLEN)
				nlioc->len = DHD_IOCTL_MAXLEN;
			buf = vzalloc(nlioc->len);
			if (!buf)
				return -ENOMEM;
			newbuf = true;
			memcpy(buf, (void *)nlioc + nlioc->offset, len);
			*(char *)(buf + len) = '\0';
		}
	}

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
	ndev = wdev_to_wlc_ndev(wdev, cfg);
	index = dhd_net2idx(dhd->info, ndev);
	if (index == DHD_BAD_IF) {
		WL_ERR(("Bad ifidx from wdev:%p\n", wdev));
		return BCME_ERROR;
	}
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */

	ioc.cmd = nlioc->cmd;
	ioc.len = nlioc->len;
	ioc.set = nlioc->set;
	ioc.driver = nlioc->magic;
	err = dhd_ioctl_process(dhd, index, &ioc, buf);
	if (err) {
		WL_TRACE(("dhd_ioctl_process return err %d\n", err));
		err = OSL_ERROR(err);
		goto done;
	}

	cur = buf;
	while (nlioc->len > 0) {
		buflen = nlioc->len > maxmsglen ? maxmsglen : nlioc->len;
		nlioc->len -= buflen;
		reply = cfg80211_testmode_alloc_reply_skb(wiphy, buflen+4);
		if (!reply) {
			WL_ERR(("Failed to allocate reply msg\n"));
			err = -ENOMEM;
			break;
		}

		if (nla_put(reply, BCM_NLATTR_DATA, buflen, cur) ||
			nla_put_u16(reply, BCM_NLATTR_LEN, buflen)) {
			kfree_skb(reply);
			err = -ENOBUFS;
			break;
		}

		do {
			err = cfg80211_testmode_reply(reply);
		} while (err == -EAGAIN);
		if (err) {
			WL_ERR(("testmode reply failed:%d\n", err));
			break;
		}
		cur += buflen;
	}

done:
	if (newbuf)
		vfree(buf);
	DHD_OS_WAKE_UNLOCK(dhd);
	return err;
}