root/drivers/net/wireless/ath/wcn36xx/testmode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wcn36xx_tm_cmd_ptt
  2. wcn36xx_tm_cmd

   1 /*
   2  * Copyright (c) 2018, The Linux Foundation. All rights reserved.
   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 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.
  15  */
  16 
  17 #include <net/netlink.h>
  18 #include <linux/firmware.h>
  19 #include <net/cfg80211.h>
  20 #include "wcn36xx.h"
  21 
  22 #include "testmode.h"
  23 #include "testmode_i.h"
  24 #include "hal.h"
  25 #include "smd.h"
  26 
  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 },
  31 };
  32 
  33 struct build_release_number {
  34         u16 drv_major;
  35         u16 drv_minor;
  36         u16 drv_patch;
  37         u16 drv_build;
  38         u16 ptt_max;
  39         u16 ptt_min;
  40         u16 fw_ver;
  41 } __packed;
  42 
  43 static int wcn36xx_tm_cmd_ptt(struct wcn36xx *wcn, struct ieee80211_vif *vif,
  44                               struct nlattr *tb[])
  45 {
  46         int ret = 0, buf_len;
  47         void *buf;
  48         struct ftm_rsp_msg *msg, *rsp = NULL;
  49         struct sk_buff *skb;
  50 
  51         if (!tb[WCN36XX_TM_ATTR_DATA])
  52                 return -EINVAL;
  53 
  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;
  57 
  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,
  61                    buf, buf_len);
  62 
  63         wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "REQ ", buf, buf_len);
  64 
  65         if (msg->msg_id == MSG_GET_BUILD_RELEASE_NUMBER) {
  66                 struct build_release_number *body =
  67                                 (struct build_release_number *)
  68                                 msg->msg_response;
  69 
  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;
  74                 body->ptt_max = 10;
  75                 body->ptt_min = 0;
  76 
  77                 rsp = msg;
  78                 rsp->resp_status = 0;
  79         } else {
  80                 wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
  81                             "PPT Request >> HAL size %d\n",
  82                                 msg->msg_body_length);
  83 
  84                 msg->resp_status = wcn36xx_smd_process_ptt_msg(wcn, vif, msg,
  85                                                                msg->msg_body_length, (void *)(&rsp));
  86 
  87                 wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
  88                             "Response status = %d\n",
  89                                 msg->resp_status);
  90                 if (rsp)
  91                         wcn36xx_dbg(WCN36XX_DBG_TESTMODE,
  92                                     "PPT Response << HAL size %d\n",
  93                                         rsp->msg_body_length);
  94         }
  95 
  96         if (!rsp) {
  97                 rsp = msg;
  98                 wcn36xx_warn("No response! Echoing request with response status %d\n",
  99                              rsp->resp_status);
 100         }
 101         wcn36xx_dbg_dump(WCN36XX_DBG_TESTMODE_DUMP, "RSP ",
 102                          rsp, rsp->msg_body_length);
 103 
 104         skb = cfg80211_testmode_alloc_reply_skb(wcn->hw->wiphy,
 105                                                 nla_total_size(msg->msg_body_length));
 106         if (!skb) {
 107                 ret = -ENOMEM;
 108                 goto out;
 109         }
 110 
 111         ret = nla_put(skb, WCN36XX_TM_ATTR_DATA, rsp->msg_body_length, rsp);
 112         if (ret) {
 113                 kfree_skb(skb);
 114                 goto out;
 115         }
 116 
 117         ret = cfg80211_testmode_reply(skb);
 118 
 119 out:
 120         if (rsp != msg)
 121                 kfree(rsp);
 122 
 123         return ret;
 124 }
 125 
 126 int wcn36xx_tm_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 127                    void *data, int len)
 128 {
 129         struct wcn36xx *wcn = hw->priv;
 130         struct nlattr *tb[WCN36XX_TM_ATTR_MAX + 1];
 131         int ret = 0;
 132         unsigned short attr;
 133 
 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);
 137         if (ret)
 138                 return ret;
 139 
 140         if (!tb[WCN36XX_TM_ATTR_CMD])
 141                 return -EINVAL;
 142 
 143         attr = nla_get_u16(tb[WCN36XX_TM_ATTR_CMD]);
 144 
 145         if (attr != WCN36XX_TM_CMD_PTT)
 146                 return -EOPNOTSUPP;
 147 
 148         return wcn36xx_tm_cmd_ptt(wcn, vif, tb);
 149 }

/* [<][>][^][v][top][bottom][index][help] */