2 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
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.
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 ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <net/netlink.h>
18 #include <linux/firmware.h>
19 #include <net/cfg80211.h>
23 #include "testmode_i.h"
27 static const struct nla_policy wcn36xx_tm_policy
[WCN36XX_TM_ATTR_MAX
+ 1] = {
28 [WCN36XX_TM_ATTR_CMD
] = { .type
= NLA_U16
},
29 [WCN36XX_TM_ATTR_DATA
] = { .type
= NLA_BINARY
,
30 .len
= WCN36XX_TM_DATA_MAX_LEN
},
33 struct build_release_number
{
43 static int wcn36xx_tm_cmd_ptt(struct wcn36xx
*wcn
, struct ieee80211_vif
*vif
,
48 struct ftm_rsp_msg
*msg
, *rsp
= NULL
;
51 if (!tb
[WCN36XX_TM_ATTR_DATA
])
54 buf
= nla_data(tb
[WCN36XX_TM_ATTR_DATA
]);
55 buf_len
= nla_len(tb
[WCN36XX_TM_ATTR_DATA
]);
56 msg
= (struct ftm_rsp_msg
*)buf
;
58 wcn36xx_dbg(WCN36XX_DBG_TESTMODE
,
59 "testmode cmd wmi msg_id 0x%04X msg_len %d buf %pK buf_len %d\n",
60 msg
->msg_id
, msg
->msg_body_length
,
63 wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP
, "REQ ", buf
, buf_len
);
65 if (msg
->msg_id
== MSG_GET_BUILD_RELEASE_NUMBER
) {
66 struct build_release_number
*body
=
67 (struct build_release_number
*)
70 body
->drv_major
= wcn
->fw_major
;
71 body
->drv_minor
= wcn
->fw_minor
;
72 body
->drv_patch
= wcn
->fw_version
;
73 body
->drv_build
= wcn
->fw_revision
;
80 wcn36xx_dbg(WCN36XX_DBG_TESTMODE
,
81 "PPT Request >> HAL size %d\n",
82 msg
->msg_body_length
);
84 msg
->resp_status
= wcn36xx_smd_process_ptt_msg(wcn
, vif
, msg
,
85 msg
->msg_body_length
, (void *)(&rsp
));
87 wcn36xx_dbg(WCN36XX_DBG_TESTMODE
,
88 "Response status = %d\n",
91 wcn36xx_dbg(WCN36XX_DBG_TESTMODE
,
92 "PPT Response << HAL size %d\n",
93 rsp
->msg_body_length
);
98 wcn36xx_warn("No response! Echoing request with response status %d\n",
101 wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP
, "RSP ",
102 rsp
, rsp
->msg_body_length
);
104 skb
= cfg80211_testmode_alloc_reply_skb(wcn
->hw
->wiphy
,
105 nla_total_size(msg
->msg_body_length
));
111 ret
= nla_put(skb
, WCN36XX_TM_ATTR_DATA
, rsp
->msg_body_length
, rsp
);
117 ret
= cfg80211_testmode_reply(skb
);
126 int wcn36xx_tm_cmd(struct ieee80211_hw
*hw
, struct ieee80211_vif
*vif
,
129 struct wcn36xx
*wcn
= hw
->priv
;
130 struct nlattr
*tb
[WCN36XX_TM_ATTR_MAX
+ 1];
134 wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP
, "Data:", data
, len
);
135 ret
= nla_parse_deprecated(tb
, WCN36XX_TM_ATTR_MAX
, data
, len
,
136 wcn36xx_tm_policy
, NULL
);
140 if (!tb
[WCN36XX_TM_ATTR_CMD
])
143 attr
= nla_get_u16(tb
[WCN36XX_TM_ATTR_CMD
]);
145 if (attr
!= WCN36XX_TM_CMD_PTT
)
148 return wcn36xx_tm_cmd_ptt(wcn
, vif
, tb
);