Merge tag 'JH7110_515_SDK_v4.0.0-rc1' into vf2-515-devel
[platform/kernel/linux-starfive.git] / drivers / net / wireless / eswin / ecrnx_iwpriv.c
1 /**
2  ******************************************************************************
3  *
4  * @file ecrnx_iwpriv.c
5  *
6  * @brief iwpriv function definitions
7  *
8  * Copyright (C) ESWIN 2015-2020
9  *
10  ******************************************************************************
11  */
12
13 /**
14  * INCLUDE FILES
15  ******************************************************************************
16  */
17 #include <net/cfg80211.h>
18 #include <net/iw_handler.h>
19 #include "ecrnx_defs.h"
20 #include "eswin_utils.h"
21
22 #ifdef CONFIG_ECRNX_WIFO_CAIL
23 #include "ecrnx_amt.h"
24 #include "core.h"
25 #endif
26
27 #ifdef CONFIG_WIRELESS_EXT
28 /**
29  * FUNCTION DEFINITIONS
30  ******************************************************************************
31  */
32 #define IN
33 #define OUT
34
35 #ifdef CONFIG_WEXT_PRIV
36  /* This may be wrong. When using the new SIOCIWFIRSTPRIV range, we probably
37   * should use only "GET" ioctls (last bit set to 1). "SET" ioctls are root
38   * only and don't return the modified struct ifreq to the application which
39   * is usually a problem. - Jean II */
40 #ifdef CONFIG_ECRNX_WIFO_CAIL
41 #define IOCTL_IWPRIV_AMT                (SIOCIWFIRSTPRIV + 1)
42 #endif
43 #define IOCTL_IWPRIV_WD                 (SIOCIWFIRSTPRIV + 3)
44
45 #if 0
46 static int priv_set_int(IN struct net_device *prNetDev,
47           IN struct iw_request_info *prIwReqInfo,
48           IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
49 {
50     int *flag = (int*)pcExtra;
51     ECRNX_PRINT("cmd=%x, flags=%x\n",
52       prIwReqInfo->cmd, prIwReqInfo->flags);
53     ECRNX_PRINT("mode=%x, flags=%x\n",
54       prIwReqData->mode, prIwReqData->data.flags);
55     *flag = 0x1234;
56     prIwReqData->param.value = 0x1230;
57
58     return 1;
59 }
60
61 /*----------------------------------------------------------------------------*/
62 /*!
63 * \brief Private ioctl get int handler.
64 *
65 * \param[in] pDev Net device requested.
66 * \param[out] pIwReq Pointer to iwreq structure.
67 * \param[in] prIwReqData The ioctl req structure, use the field of sub-command.
68 * \param[out] pcExtra The buffer with put the return value
69 *
70 * \retval 0 For success.
71 * \retval -EOPNOTSUPP If cmd is not supported.
72 * \retval -EFAULT For fail.
73 *
74 */
75 /*----------------------------------------------------------------------------*/
76 static int priv_get_int(IN struct net_device *prNetDev,
77       IN struct iw_request_info *prIwReqInfo,
78       IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
79 {
80     int status = 0;
81     prIwReqData->mode = 0xabcd;
82     return status;
83 }               /* __priv_get_int */
84
85 static int priv_set_struct(IN struct net_device *prNetDev,
86        IN struct iw_request_info *prIwReqInfo,
87        IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
88 {
89   ECRNX_PRINT("cmd=%x, flags=%x\n",
90        prIwReqInfo->cmd, prIwReqInfo->flags);
91   ECRNX_PRINT("mode=%x, flags=%x\n",
92        prIwReqData->mode, prIwReqData->data.flags);
93
94   return 0;
95   //return compat_priv(prNetDev, prIwReqInfo,
96   //     prIwReqData, pcExtra, __priv_set_struct);
97 }
98
99 static int priv_get_struct(IN struct net_device *prNetDev,
100        IN struct iw_request_info *prIwReqInfo,
101        IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
102 {
103     ECRNX_PRINT("cmd=%x, flags=%x\n",
104        prIwReqInfo->cmd, prIwReqInfo->flags);
105     ECRNX_PRINT("mode=%x, flags=%x\n",
106        prIwReqData->mode, prIwReqData->data.flags);
107
108     prIwReqData->data.length = 6;
109     memcpy(pcExtra, "ecrnx", 6);
110     return 0;
111
112 }
113
114 static int priv_get_mac(IN struct net_device *prNetDev,
115      IN struct iw_request_info *prIwReqInfo,
116      IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
117 {
118     struct sockaddr *dst = (struct sockaddr *) pcExtra;
119     struct ecrnx_vif *vif;
120     dbg_req_t req;
121
122     req.dbg_level = DBG_TYPE_D;
123     req.direct = 0;
124
125     vif = netdev_priv(prNetDev);
126     //send cmd to slave
127     ECRNX_PRINT("priv_get_mac: send cmd to slave \n");
128     host_send(&req, sizeof(dbg_req_t), TX_FLAG_IWPRIV_IE);
129     //wait for slave confirm
130     vif->rxdatas = 0;
131     wait_event_interruptible_timeout(vif->rxdataq, vif->rxdatas, 2*HZ);
132
133     ECRNX_PRINT("priv_get_mac: rx_len:%d \n", vif->rxlen);
134     if (!vif->rxlen)
135         return -1;
136
137     prIwReqData->data.length = vif->rxlen;
138     memcpy(dst->sa_data, vif->rxdata, vif->rxlen);
139     dst->sa_family = 1;
140     prIwReqData->data.length = 1;
141
142     return 0;
143 }
144
145 static int priv_get_vers(IN struct net_device *prNetDev,
146       IN struct iw_request_info *prIwReqInfo,
147       IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
148 {
149     ECRNX_PRINT("get vers cmd=%x, flags=%x\n", prIwReqInfo->cmd, prIwReqInfo->flags);
150     ECRNX_PRINT("mode=%x, flags=%x\n", prIwReqData->mode, prIwReqData->data.flags);
151
152    memcpy(pcExtra, "1.0.1", 6);
153    prIwReqData->data.length = 6;
154
155     return 0;
156 }
157
158
159 static int priv_set_debug_level(IN struct net_device *prNetDev,
160       IN struct iw_request_info *prIwReqInfo,
161       IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
162 {
163     ECRNX_PRINT("priv_set_debug_level cmd=%x, flags=%x\n",
164     prIwReqInfo->cmd, prIwReqInfo->flags);
165     ECRNX_PRINT("mode=%x, flags=%x\n",
166     prIwReqData->mode, prIwReqData->data.flags);
167
168     ECRNX_PRINT("param_value:%d \n", prIwReqData->param.value);
169
170     ecrnx_dbg_level = prIwReqData->param.value;
171     return 0;
172 }
173 #endif
174
175 #ifdef CONFIG_ECRNX_WIFO_CAIL
176 static int priv_amt(IN struct net_device *prNetDev,
177      IN struct iw_request_info *prIwReqInfo,
178      IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
179 {
180     struct sockaddr *dst = (struct sockaddr *) pcExtra;
181
182         if (amt_mode == false) {
183                 ECRNX_ERR(" The current mode does not support the AMT commands!!\n");
184                 return -1;
185         }
186 //      printk("buff:%s, len:%d\n", prIwReqData->data.pointer, prIwReqData->data.length);
187     //send cmd to slave
188     char *reqdata = kzalloc(prIwReqData->data.length, GFP_KERNEL);
189     if (!reqdata){
190         return 0;
191     }
192     if (copy_from_user(reqdata, prIwReqData->data.pointer, prIwReqData->data.length)) {
193         return 0;
194     }
195     host_send(reqdata, prIwReqData->data.length, TX_FLAG_AMT_IWPRIV_IE);
196     kfree(reqdata);
197
198     //wait for slave confirm
199     amt_vif.rxdatas = 0;
200         amt_vif.rxlen = 0;
201
202     wait_event_interruptible_timeout(amt_vif.rxdataq, amt_vif.rxdatas, 2*HZ);
203
204     ECRNX_PRINT("rxdatas: rx_len:%d, rxdata:[%s]\n", amt_vif.rxlen,amt_vif.rxdata);
205     if (!amt_vif.rxdatas){
206         return -1;
207     }
208
209         prIwReqData->data.length = amt_vif.rxlen;
210         memcpy(dst->sa_data, amt_vif.rxdata, amt_vif.rxlen);
211         dst->sa_family = 1;
212         memcpy(pcExtra, amt_vif.rxdata, amt_vif.rxlen);
213
214     return 0;
215 }
216 #endif
217
218 static struct ecrnx_vif *get_priv_vif(struct ecrnx_hw *ecrnx_hw)
219 {
220      return ecrnx_hw->vif_table[0];
221 }
222
223 void priv_copy_data_wakeup(struct ecrnx_hw *ecrnx_hw, struct sk_buff *skb)
224 {
225     struct ecrnx_vif* ecrnx_vif = get_priv_vif(ecrnx_hw);
226
227     ECRNX_PRINT("iw_cfm vif_start:%d, vif_monitor:%d \n", ecrnx_hw->vif_started, ecrnx_hw->monitor_vif);
228     //print_hex_dump(KERN_INFO, DBG_PREFIX_IW_CFM, DUMP_PREFIX_ADDRESS, 32, 1, skb->data, skb->len, false);
229     if (ECRNX_RXSIZE > skb->len) {
230         ecrnx_vif->rxlen = skb->len;
231     } else {
232         ecrnx_vif->rxlen = ECRNX_RXSIZE;
233     }
234
235     memcpy(ecrnx_vif->rxdata, skb->data, ecrnx_vif->rxlen);
236     ecrnx_vif->rxdatas = 1;
237     wake_up(&ecrnx_vif->rxdataq);
238 }
239
240 static int priv_wd(IN struct net_device *prNetDev,
241      IN struct iw_request_info *prIwReqInfo,
242      IN union iwreq_data *prIwReqData, IN OUT char *pcExtra)
243 {
244     struct sockaddr *dst = (struct sockaddr *) pcExtra;
245     struct ecrnx_vif *vif;
246
247     //printk("priv_wd:%s, len:%d\n", prIwReqData->data.pointer, prIwReqData->data.length);
248     //send cmd to slave
249     char *reqdata = kzalloc(prIwReqData->data.length, GFP_KERNEL);
250     if (!reqdata){
251         return 0;
252     }
253
254     if (copy_from_user(reqdata, prIwReqData->data.pointer, prIwReqData->data.length)) {
255         return 0;
256     }
257     host_send(reqdata, prIwReqData->data.length, TX_FLAG_IWPRIV_IE);
258     kfree(reqdata);
259
260     //wait for slave confirm
261     vif = netdev_priv(prNetDev);
262     vif = get_priv_vif(vif->ecrnx_hw);
263     vif->rxdatas = 0;
264     wait_event_interruptible_timeout(vif->rxdataq, vif->rxdatas, 2*HZ);
265
266     if (!vif->rxdatas)
267         return -1;
268     
269     ECRNX_PRINT("priv_wd: rx_len:%d rxdata:[%s]\n", vif->rxlen, vif->rxdata);
270     prIwReqData->data.length = vif->rxlen;
271     memcpy(dst->sa_data, vif->rxdata, vif->rxlen);
272     dst->sa_family = 1;
273     memcpy(pcExtra, vif->rxdata, vif->rxlen);
274
275     return 0;
276 }
277
278 /*
279  * Structures to export the Wireless Handlers
280  */
281 static const struct iw_priv_args ecrnx_wext_private_args[] = {
282 #ifdef CONFIG_ECRNX_WIFO_CAIL
283         {IOCTL_IWPRIV_AMT, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | 2000, "amt"},
284 #endif
285     {IOCTL_IWPRIV_WD, IW_PRIV_TYPE_CHAR | 2000, IW_PRIV_TYPE_CHAR | 2000, "wd"},
286 };
287
288 const iw_handler ecrnx_wext_private_handler[] = {
289 #ifdef CONFIG_ECRNX_WIFO_CAIL
290     [IOCTL_IWPRIV_AMT - SIOCIWFIRSTPRIV] = priv_amt,
291 #endif
292     [IOCTL_IWPRIV_WD - SIOCIWFIRSTPRIV] = priv_wd,
293 };
294
295 #endif
296
297 /*------------------------------------------------------------------*/
298 /*
299 * Commit handler : called after a bunch of SET operations
300 */
301 static int ecrnx_wext_config_commit(struct net_device *dev,
302                struct iw_request_info *info, /* NULL */
303                void *zwrq,           /* NULL */
304                char *extra)          /* NULL */
305 {
306     return 1;
307 }
308
309 static int ecrnx_wext_get_name(struct net_device *dev,
310         struct iw_request_info *info,
311         char *cwrq,
312         char *extra)
313 {
314     strcpy(cwrq, "IEEE 802.11");
315     return 0;
316 }
317
318 /*------------------------------------------------------------------*/
319 /*
320  * Wireless Handler : set frequency
321  */
322 static int ecrnx_wext_set_freq(struct net_device *dev,
323              struct iw_request_info *info,
324              struct iw_freq *fwrq,
325              char *extra)
326 {
327     int rc = -EINPROGRESS;      /* Call commit handler */
328     ECRNX_PRINT("fwrq->e:%d, fwrq->m:%d \n", fwrq->e, fwrq->m);
329     return rc;
330 }
331
332 /*------------------------------------------------------------------*/
333 /*
334  * Wireless Handler : get frequency
335  */
336 static int ecrnx_wext_get_freq(struct net_device *dev,
337              struct iw_request_info *info,
338              struct iw_freq *fwrq,
339              char *extra)
340 {
341      fwrq->m = 100000 *
342             2.412;
343      fwrq->e = 1;
344     return 0;
345 }
346
347 /*------------------------------------------------------------------*/
348 /*
349  * Wireless Handler : set Mode of Operation
350  */
351 static int ecrnx_wext_set_mode(struct net_device *dev,
352              struct iw_request_info *info,
353              __u32 *uwrq,
354              char *extra)
355 {
356    ECRNX_PRINT("*uwrq:%d \n", *uwrq);
357     return -EINPROGRESS;        /* Call commit handler */
358 }
359
360 /*------------------------------------------------------------------*/
361 /*
362  * Wireless Handler : get Mode of Operation
363  */
364 static int ecrnx_wext_get_mode(struct net_device *dev,
365              struct iw_request_info *info,
366              __u32 *uwrq,
367              char *extra)
368 {
369    *uwrq = 0xFFEE;
370     return 0;
371 }
372
373 static const iw_handler     ecrnx_wext_handler[] =
374 {
375     (iw_handler) ecrnx_wext_config_commit,    /* SIOCSIWCOMMIT */
376     (iw_handler) ecrnx_wext_get_name,     /* SIOCGIWNAME */
377      (iw_handler) NULL,          /* SIOCSIWNWID */
378     (iw_handler) NULL,          /* SIOCGIWNWID */
379     (iw_handler) ecrnx_wext_set_freq,     /* SIOCSIWFREQ */
380     (iw_handler) ecrnx_wext_get_freq,     /* SIOCGIWFREQ */
381     (iw_handler) ecrnx_wext_set_mode,     /* SIOCSIWMODE */
382     (iw_handler) ecrnx_wext_get_mode,     /* SIOCGIWMODE */
383 };
384
385 const struct iw_handler_def  ecrnx_wext_handler_def =
386 {
387     .num_standard   = ARRAY_SIZE(ecrnx_wext_handler),
388     .standard   = ecrnx_wext_handler,
389 #ifdef CONFIG_WEXT_PRIV
390     .num_private    = ARRAY_SIZE(ecrnx_wext_private_handler),
391     .num_private_args = ARRAY_SIZE(ecrnx_wext_private_args),
392     .private    = ecrnx_wext_private_handler,
393     .private_args   = ecrnx_wext_private_args,
394 #endif
395 };
396 #endif