testmode.c (0d2cd91bf7b1a7cc1d638296111fcc2bcf5c0bb4) | testmode.c (4f34dacea117029dbad1f0f50d68207b97546d1e) |
---|---|
1/* 2 * Copyright (c) 2010-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "testmode.h" | 1/* 2 * Copyright (c) 2010-2011 Atheros Communications Inc. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17#include "testmode.h" |
18#include "debug.h" |
|
18 19#include <net/netlink.h> 20 21enum ath6kl_tm_attr { 22 __ATH6KL_TM_ATTR_INVALID = 0, 23 ATH6KL_TM_ATTR_CMD = 1, 24 ATH6KL_TM_ATTR_DATA = 2, 25 26 /* keep last */ 27 __ATH6KL_TM_ATTR_AFTER_LAST, 28 ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1, 29}; 30 31enum ath6kl_tm_cmd { 32 ATH6KL_TM_CMD_TCMD = 0, | 19 20#include <net/netlink.h> 21 22enum ath6kl_tm_attr { 23 __ATH6KL_TM_ATTR_INVALID = 0, 24 ATH6KL_TM_ATTR_CMD = 1, 25 ATH6KL_TM_ATTR_DATA = 2, 26 27 /* keep last */ 28 __ATH6KL_TM_ATTR_AFTER_LAST, 29 ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1, 30}; 31 32enum ath6kl_tm_cmd { 33 ATH6KL_TM_CMD_TCMD = 0, |
33 ATH6KL_TM_CMD_RX_REPORT = 1, | 34 ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */ |
34}; 35 36#define ATH6KL_TM_DATA_MAX_LEN 5000 37 38static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { 39 [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 }, 40 [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY, 41 .len = ATH6KL_TM_DATA_MAX_LEN }, 42}; 43 | 35}; 36 37#define ATH6KL_TM_DATA_MAX_LEN 5000 38 39static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { 40 [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 }, 41 [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY, 42 .len = ATH6KL_TM_DATA_MAX_LEN }, 43}; 44 |
44void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) | 45void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len) |
45{ | 46{ |
46 if (down_interruptible(&ar->sem)) | 47 struct sk_buff *skb; 48 49 if (!buf || buf_len == 0) |
47 return; 48 | 50 return; 51 |
49 kfree(ar->tm.rx_report); 50 51 ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); 52 ar->tm.rx_report_len = buf_len; 53 54 up(&ar->sem); 55 56 wake_up(&ar->event_wq); 57} 58 59static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, 60 struct sk_buff *skb) 61{ 62 int ret = 0; 63 long left; 64 65 if (down_interruptible(&ar->sem)) 66 return -ERESTARTSYS; 67 68 if (!test_bit(WMI_READY, &ar->flag)) { 69 ret = -EIO; 70 goto out; | 52 skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL); 53 if (!skb) { 54 ath6kl_warn("failed to allocate testmode rx skb!\n"); 55 return; |
71 } | 56 } |
57 NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_TCMD); 58 NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf); 59 cfg80211_testmode_event(skb, GFP_KERNEL); 60 return; |
|
72 | 61 |
73 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { 74 ret = -EBUSY; 75 goto out; 76 } 77 78 if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { 79 up(&ar->sem); 80 return -EIO; 81 } 82 83 left = wait_event_interruptible_timeout(ar->event_wq, 84 ar->tm.rx_report != NULL, 85 WMI_TIMEOUT); 86 87 if (left == 0) { 88 ret = -ETIMEDOUT; 89 goto out; 90 } else if (left < 0) { 91 ret = left; 92 goto out; 93 } 94 95 if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { 96 ret = -EINVAL; 97 goto out; 98 } 99 100 NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, 101 ar->tm.rx_report); 102 103 kfree(ar->tm.rx_report); 104 ar->tm.rx_report = NULL; 105 106out: 107 up(&ar->sem); 108 109 return ret; 110 | |
111nla_put_failure: | 62nla_put_failure: |
112 ret = -ENOBUFS; 113 goto out; | 63 kfree_skb(skb); 64 ath6kl_warn("nla_put failed on testmode rx skb!\n"); |
114} 115 116int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) 117{ 118 struct ath6kl *ar = wiphy_priv(wiphy); 119 struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; | 65} 66 67int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) 68{ 69 struct ath6kl *ar = wiphy_priv(wiphy); 70 struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; |
120 int err, buf_len, reply_len; 121 struct sk_buff *skb; | 71 int err, buf_len; |
122 void *buf; 123 124 err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, 125 ath6kl_tm_policy); 126 if (err) 127 return err; 128 129 if (!tb[ATH6KL_TM_ATTR_CMD]) --- 8 unchanged lines hidden (view full) --- 138 buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); 139 140 ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); 141 142 return 0; 143 144 break; 145 case ATH6KL_TM_CMD_RX_REPORT: | 72 void *buf; 73 74 err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, 75 ath6kl_tm_policy); 76 if (err) 77 return err; 78 79 if (!tb[ATH6KL_TM_ATTR_CMD]) --- 8 unchanged lines hidden (view full) --- 88 buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); 89 90 ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); 91 92 return 0; 93 94 break; 95 case ATH6KL_TM_CMD_RX_REPORT: |
146 if (!tb[ATH6KL_TM_ATTR_DATA]) 147 return -EINVAL; 148 149 buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); 150 buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); 151 152 reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); 153 skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); 154 if (!skb) 155 return -ENOMEM; 156 157 err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); 158 if (err < 0) { 159 kfree_skb(skb); 160 return err; 161 } 162 163 return cfg80211_testmode_reply(skb); | |
164 default: 165 return -EOPNOTSUPP; 166 } 167} | 96 default: 97 return -EOPNOTSUPP; 98 } 99} |