wlcore: handle smart config vendor commands
userspace can ask to perform various smart config actions via custom vendor commands. Signed-off-by: Eliad Peller <eliad@wizery.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
ccb1df9480
commit
80ff8063e8
|
@ -1,5 +1,5 @@
|
|||
wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
|
||||
boot.o init.o debugfs.o scan.o sysfs.o
|
||||
boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o
|
||||
|
||||
wlcore_spi-objs = spi.o
|
||||
wlcore_sdio-objs = sdio.o
|
||||
|
|
184
drivers/net/wireless/ti/wlcore/vendor_cmd.c
Normal file
184
drivers/net/wireless/ti/wlcore/vendor_cmd.c
Normal file
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* This file is part of wlcore
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <net/mac80211.h>
|
||||
#include <net/netlink.h>
|
||||
|
||||
#include "wlcore.h"
|
||||
#include "debug.h"
|
||||
#include "ps.h"
|
||||
#include "hw_ops.h"
|
||||
#include "vendor_cmd.h"
|
||||
|
||||
static const
|
||||
struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
|
||||
[WLCORE_VENDOR_ATTR_FREQ] = { .type = NLA_U32 },
|
||||
[WLCORE_VENDOR_ATTR_GROUP_ID] = { .type = NLA_U32 },
|
||||
[WLCORE_VENDOR_ATTR_GROUP_KEY] = { .type = NLA_U32,
|
||||
.len = WLAN_MAX_KEY_LEN },
|
||||
};
|
||||
|
||||
static int
|
||||
wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
|
||||
wlcore_vendor_attr_policy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wlcore_smart_config_start(wl,
|
||||
nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct wl1271 *wl = hw->priv;
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wlcore_smart_config_stop(wl);
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
|
||||
struct wireless_dev *wdev,
|
||||
const void *data, int data_len)
|
||||
{
|
||||
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
|
||||
struct wl1271 *wl = hw->priv;
|
||||
struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
|
||||
int ret;
|
||||
|
||||
wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
|
||||
|
||||
if (!data)
|
||||
return -EINVAL;
|
||||
|
||||
ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
|
||||
wlcore_vendor_attr_policy);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
|
||||
!tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&wl->mutex);
|
||||
|
||||
if (unlikely(wl->state != WLCORE_STATE_ON)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = wl1271_ps_elp_wakeup(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
ret = wlcore_smart_config_set_group_key(wl,
|
||||
nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
|
||||
nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
|
||||
nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
|
||||
|
||||
wl1271_ps_elp_sleep(wl);
|
||||
out:
|
||||
mutex_unlock(&wl->mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
|
||||
{
|
||||
.info = {
|
||||
.vendor_id = TI_OUI,
|
||||
.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
|
||||
WIPHY_VENDOR_CMD_NEED_RUNNING,
|
||||
.doit = wlcore_vendor_cmd_smart_config_start,
|
||||
},
|
||||
{
|
||||
.info = {
|
||||
.vendor_id = TI_OUI,
|
||||
.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
|
||||
WIPHY_VENDOR_CMD_NEED_RUNNING,
|
||||
.doit = wlcore_vendor_cmd_smart_config_stop,
|
||||
},
|
||||
{
|
||||
.info = {
|
||||
.vendor_id = TI_OUI,
|
||||
.subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
|
||||
},
|
||||
.flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
|
||||
WIPHY_VENDOR_CMD_NEED_RUNNING,
|
||||
.doit = wlcore_vendor_cmd_smart_config_set_group_key,
|
||||
},
|
||||
};
|
||||
|
||||
void wlcore_set_vendor_commands(struct wiphy *wiphy)
|
||||
{
|
||||
wiphy->vendor_commands = wlcore_vendor_commands;
|
||||
wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
|
||||
}
|
36
drivers/net/wireless/ti/wlcore/vendor_cmd.h
Normal file
36
drivers/net/wireless/ti/wlcore/vendor_cmd.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* This file is part of wlcore
|
||||
*
|
||||
* Copyright (C) 2014 Texas Instruments. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2 as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __WLCORE_VENDOR_H__
|
||||
#define __WLCORE_VENDOR_H__
|
||||
|
||||
#define TI_OUI 0x080028
|
||||
|
||||
enum wlcore_vendor_commands {
|
||||
WLCORE_VENDOR_CMD_SMART_CONFIG_START,
|
||||
WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
|
||||
WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
|
||||
|
||||
NUM_WLCORE_VENDOR_CMD,
|
||||
MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1
|
||||
};
|
||||
|
||||
enum wlcore_vendor_attributes {
|
||||
WLCORE_VENDOR_ATTR_FREQ,
|
||||
WLCORE_VENDOR_ATTR_PSK,
|
||||
WLCORE_VENDOR_ATTR_SSID,
|
||||
WLCORE_VENDOR_ATTR_GROUP_ID,
|
||||
WLCORE_VENDOR_ATTR_GROUP_KEY,
|
||||
|
||||
NUM_WLCORE_VENDOR_ATTR,
|
||||
MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1
|
||||
};
|
||||
|
||||
#endif /* __WLCORE_VENDOR_H__ */
|
Loading…
Reference in a new issue