Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eliad Peller and committed by
John W. Linville
80ff8063 ccb1df94

+221 -1
+1 -1
drivers/net/wireless/ti/wlcore/Makefile
··· 1 1 wlcore-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 4 4 wlcore_spi-objs = spi.o 5 5 wlcore_sdio-objs = sdio.o
+184
drivers/net/wireless/ti/wlcore/vendor_cmd.c
··· 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 + 20 + static const 21 + struct 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 + 28 + static int 29 + wlcore_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); 66 + out: 67 + mutex_unlock(&wl->mutex); 68 + 69 + return 0; 70 + } 71 + 72 + static int 73 + wlcore_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); 97 + out: 98 + mutex_unlock(&wl->mutex); 99 + 100 + return ret; 101 + } 102 + 103 + static int 104 + wlcore_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); 144 + out: 145 + mutex_unlock(&wl->mutex); 146 + 147 + return ret; 148 + } 149 + 150 + static 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 + 180 + void 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 + }
+36
drivers/net/wireless/ti/wlcore/vendor_cmd.h
··· 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 + 16 + enum 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 + 25 + enum 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__ */