aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti
diff options
context:
space:
mode:
authorEliad Peller <eliad@wizery.com>2014-07-10 20:01:32 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-07-15 15:59:56 -0400
commit80ff8063e87c352072c6d96fb2d87becaf591966 (patch)
treea2470bcaa27a448b40694c4b51e487ab6e68e609 /drivers/net/wireless/ti
parentccb1df948085abcac0a91154e9cabeb563b65833 (diff)
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>
Diffstat (limited to 'drivers/net/wireless/ti')
-rw-r--r--drivers/net/wireless/ti/wlcore/Makefile2
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.c184
-rw-r--r--drivers/net/wireless/ti/wlcore/vendor_cmd.h36
3 files changed, 221 insertions, 1 deletions
diff --git a/drivers/net/wireless/ti/wlcore/Makefile b/drivers/net/wireless/ti/wlcore/Makefile
index 4f23931d7bd5..0a69c1373643 100644
--- a/drivers/net/wireless/ti/wlcore/Makefile
+++ b/drivers/net/wireless/ti/wlcore/Makefile
@@ -1,5 +1,5 @@
1wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ 1wlcore-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
2 boot.o init.o debugfs.o scan.o sysfs.o 2 boot.o init.o debugfs.o scan.o sysfs.o vendor_cmd.o
3 3
4wlcore_spi-objs = spi.o 4wlcore_spi-objs = spi.o
5wlcore_sdio-objs = sdio.o 5wlcore_sdio-objs = sdio.o
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.c b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
new file mode 100644
index 000000000000..98852b2ceb4d
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.c
@@ -0,0 +1,184 @@
1/*
2 * This file is part of wlcore
3 *
4 * Copyright (C) 2014 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 */
10
11#include <net/mac80211.h>
12#include <net/netlink.h>
13
14#include "wlcore.h"
15#include "debug.h"
16#include "ps.h"
17#include "hw_ops.h"
18#include "vendor_cmd.h"
19
20static const
21struct nla_policy wlcore_vendor_attr_policy[NUM_WLCORE_VENDOR_ATTR] = {
22 [WLCORE_VENDOR_ATTR_FREQ] = { .type = NLA_U32 },
23 [WLCORE_VENDOR_ATTR_GROUP_ID] = { .type = NLA_U32 },
24 [WLCORE_VENDOR_ATTR_GROUP_KEY] = { .type = NLA_U32,
25 .len = WLAN_MAX_KEY_LEN },
26};
27
28static int
29wlcore_vendor_cmd_smart_config_start(struct wiphy *wiphy,
30 struct wireless_dev *wdev,
31 const void *data, int data_len)
32{
33 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
34 struct wl1271 *wl = hw->priv;
35 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
36 int ret;
37
38 wl1271_debug(DEBUG_CMD, "vendor cmd smart config start");
39
40 if (!data)
41 return -EINVAL;
42
43 ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
44 wlcore_vendor_attr_policy);
45 if (ret)
46 return ret;
47
48 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID])
49 return -EINVAL;
50
51 mutex_lock(&wl->mutex);
52
53 if (unlikely(wl->state != WLCORE_STATE_ON)) {
54 ret = -EINVAL;
55 goto out;
56 }
57
58 ret = wl1271_ps_elp_wakeup(wl);
59 if (ret < 0)
60 goto out;
61
62 ret = wlcore_smart_config_start(wl,
63 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]));
64
65 wl1271_ps_elp_sleep(wl);
66out:
67 mutex_unlock(&wl->mutex);
68
69 return 0;
70}
71
72static int
73wlcore_vendor_cmd_smart_config_stop(struct wiphy *wiphy,
74 struct wireless_dev *wdev,
75 const void *data, int data_len)
76{
77 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
78 struct wl1271 *wl = hw->priv;
79 int ret;
80
81 wl1271_debug(DEBUG_CMD, "testmode cmd smart config stop");
82
83 mutex_lock(&wl->mutex);
84
85 if (unlikely(wl->state != WLCORE_STATE_ON)) {
86 ret = -EINVAL;
87 goto out;
88 }
89
90 ret = wl1271_ps_elp_wakeup(wl);
91 if (ret < 0)
92 goto out;
93
94 ret = wlcore_smart_config_stop(wl);
95
96 wl1271_ps_elp_sleep(wl);
97out:
98 mutex_unlock(&wl->mutex);
99
100 return ret;
101}
102
103static int
104wlcore_vendor_cmd_smart_config_set_group_key(struct wiphy *wiphy,
105 struct wireless_dev *wdev,
106 const void *data, int data_len)
107{
108 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
109 struct wl1271 *wl = hw->priv;
110 struct nlattr *tb[NUM_WLCORE_VENDOR_ATTR];
111 int ret;
112
113 wl1271_debug(DEBUG_CMD, "testmode cmd smart config set group key");
114
115 if (!data)
116 return -EINVAL;
117
118 ret = nla_parse(tb, MAX_WLCORE_VENDOR_ATTR, data, data_len,
119 wlcore_vendor_attr_policy);
120 if (ret)
121 return ret;
122
123 if (!tb[WLCORE_VENDOR_ATTR_GROUP_ID] ||
124 !tb[WLCORE_VENDOR_ATTR_GROUP_KEY])
125 return -EINVAL;
126
127 mutex_lock(&wl->mutex);
128
129 if (unlikely(wl->state != WLCORE_STATE_ON)) {
130 ret = -EINVAL;
131 goto out;
132 }
133
134 ret = wl1271_ps_elp_wakeup(wl);
135 if (ret < 0)
136 goto out;
137
138 ret = wlcore_smart_config_set_group_key(wl,
139 nla_get_u32(tb[WLCORE_VENDOR_ATTR_GROUP_ID]),
140 nla_len(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]),
141 nla_data(tb[WLCORE_VENDOR_ATTR_GROUP_KEY]));
142
143 wl1271_ps_elp_sleep(wl);
144out:
145 mutex_unlock(&wl->mutex);
146
147 return ret;
148}
149
150static const struct wiphy_vendor_command wlcore_vendor_commands[] = {
151 {
152 .info = {
153 .vendor_id = TI_OUI,
154 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_START,
155 },
156 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
157 WIPHY_VENDOR_CMD_NEED_RUNNING,
158 .doit = wlcore_vendor_cmd_smart_config_start,
159 },
160 {
161 .info = {
162 .vendor_id = TI_OUI,
163 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
164 },
165 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
166 WIPHY_VENDOR_CMD_NEED_RUNNING,
167 .doit = wlcore_vendor_cmd_smart_config_stop,
168 },
169 {
170 .info = {
171 .vendor_id = TI_OUI,
172 .subcmd = WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
173 },
174 .flags = WIPHY_VENDOR_CMD_NEED_NETDEV |
175 WIPHY_VENDOR_CMD_NEED_RUNNING,
176 .doit = wlcore_vendor_cmd_smart_config_set_group_key,
177 },
178};
179
180void wlcore_set_vendor_commands(struct wiphy *wiphy)
181{
182 wiphy->vendor_commands = wlcore_vendor_commands;
183 wiphy->n_vendor_commands = ARRAY_SIZE(wlcore_vendor_commands);
184}
diff --git a/drivers/net/wireless/ti/wlcore/vendor_cmd.h b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
new file mode 100644
index 000000000000..7e8e92fad16c
--- /dev/null
+++ b/drivers/net/wireless/ti/wlcore/vendor_cmd.h
@@ -0,0 +1,36 @@
1/*
2 * This file is part of wlcore
3 *
4 * Copyright (C) 2014 Texas Instruments. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 */
10
11#ifndef __WLCORE_VENDOR_H__
12#define __WLCORE_VENDOR_H__
13
14#define TI_OUI 0x080028
15
16enum wlcore_vendor_commands {
17 WLCORE_VENDOR_CMD_SMART_CONFIG_START,
18 WLCORE_VENDOR_CMD_SMART_CONFIG_STOP,
19 WLCORE_VENDOR_CMD_SMART_CONFIG_SET_GROUP_KEY,
20
21 NUM_WLCORE_VENDOR_CMD,
22 MAX_WLCORE_VENDOR_CMD = NUM_WLCORE_VENDOR_CMD - 1
23};
24
25enum wlcore_vendor_attributes {
26 WLCORE_VENDOR_ATTR_FREQ,
27 WLCORE_VENDOR_ATTR_PSK,
28 WLCORE_VENDOR_ATTR_SSID,
29 WLCORE_VENDOR_ATTR_GROUP_ID,
30 WLCORE_VENDOR_ATTR_GROUP_KEY,
31
32 NUM_WLCORE_VENDOR_ATTR,
33 MAX_WLCORE_VENDOR_ATTR = NUM_WLCORE_VENDOR_ATTR - 1
34};
35
36#endif /* __WLCORE_VENDOR_H__ */