Commit | Line | Data |
---|---|---|
003353b0 KV |
1 | /* |
2 | * Copyright (c) 2010-2011 Atheros Communications Inc. | |
1b2df407 | 3 | * Copyright (c) 2011 Qualcomm Atheros, Inc. |
003353b0 KV |
4 | * |
5 | * Permission to use, copy, modify, and/or distribute this software for any | |
6 | * purpose with or without fee is hereby granted, provided that the above | |
7 | * copyright notice and this permission notice appear in all copies. | |
8 | * | |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
16 | */ | |
17 | ||
18 | #include "testmode.h" | |
4f34dace | 19 | #include "debug.h" |
003353b0 KV |
20 | |
21 | #include <net/netlink.h> | |
22 | ||
23 | enum ath6kl_tm_attr { | |
24 | __ATH6KL_TM_ATTR_INVALID = 0, | |
25 | ATH6KL_TM_ATTR_CMD = 1, | |
26 | ATH6KL_TM_ATTR_DATA = 2, | |
27 | ||
28 | /* keep last */ | |
29 | __ATH6KL_TM_ATTR_AFTER_LAST, | |
30 | ATH6KL_TM_ATTR_MAX = __ATH6KL_TM_ATTR_AFTER_LAST - 1, | |
31 | }; | |
32 | ||
33 | enum ath6kl_tm_cmd { | |
34 | ATH6KL_TM_CMD_TCMD = 0, | |
4f34dace | 35 | ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */ |
003353b0 KV |
36 | }; |
37 | ||
38 | #define ATH6KL_TM_DATA_MAX_LEN 5000 | |
39 | ||
40 | static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { | |
41 | [ATH6KL_TM_ATTR_CMD] = { .type = NLA_U32 }, | |
42 | [ATH6KL_TM_ATTR_DATA] = { .type = NLA_BINARY, | |
43 | .len = ATH6KL_TM_DATA_MAX_LEN }, | |
44 | }; | |
45 | ||
4f34dace | 46 | void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len) |
003353b0 | 47 | { |
4f34dace | 48 | struct sk_buff *skb; |
003353b0 | 49 | |
4f34dace TP |
50 | if (!buf || buf_len == 0) |
51 | return; | |
003353b0 | 52 | |
4f34dace TP |
53 | skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL); |
54 | if (!skb) { | |
55 | ath6kl_warn("failed to allocate testmode rx skb!\n"); | |
56 | return; | |
003353b0 | 57 | } |
4f34dace TP |
58 | NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_TCMD); |
59 | NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf); | |
60 | cfg80211_testmode_event(skb, GFP_KERNEL); | |
61 | return; | |
003353b0 KV |
62 | |
63 | nla_put_failure: | |
4f34dace TP |
64 | kfree_skb(skb); |
65 | ath6kl_warn("nla_put failed on testmode rx skb!\n"); | |
003353b0 KV |
66 | } |
67 | ||
68 | int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) | |
69 | { | |
70 | struct ath6kl *ar = wiphy_priv(wiphy); | |
71 | struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; | |
4f34dace | 72 | int err, buf_len; |
003353b0 KV |
73 | void *buf; |
74 | ||
75 | err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, | |
76 | ath6kl_tm_policy); | |
77 | if (err) | |
78 | return err; | |
79 | ||
80 | if (!tb[ATH6KL_TM_ATTR_CMD]) | |
81 | return -EINVAL; | |
82 | ||
83 | switch (nla_get_u32(tb[ATH6KL_TM_ATTR_CMD])) { | |
84 | case ATH6KL_TM_CMD_TCMD: | |
85 | if (!tb[ATH6KL_TM_ATTR_DATA]) | |
86 | return -EINVAL; | |
87 | ||
88 | buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); | |
89 | buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); | |
90 | ||
91 | ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len); | |
92 | ||
93 | return 0; | |
94 | ||
95 | break; | |
96 | case ATH6KL_TM_CMD_RX_REPORT: | |
003353b0 KV |
97 | default: |
98 | return -EOPNOTSUPP; | |
99 | } | |
100 | } |