xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/ssv6xxx/smac/smartlink.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (c) 2015 South Silicon Valley Microelectronics Inc.
3  * Copyright (c) 2015 iComm Corporation
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/init.h>
20 #include <net/sock.h>
21 #include <linux/socket.h>
22 #include <linux/net.h>
23 #include <asm/types.h>
24 #include <linux/netlink.h>
25 #include <linux/skbuff.h>
26 #include <linux/version.h>
27 #include <ssv6200.h>
28 #include "lib.h"
29 #include "dev.h"
30 #define NETLINK_SMARTLINK (31)
31 #define MAX_PAYLOAD (2048)
32 static struct sock *nl_sk = NULL;
33 struct ssv_softc *ssv_smartlink_sc = NULL;
34 EXPORT_SYMBOL(ssv_smartlink_sc);
35 u32 ssv_smartlink_status=0;
_ksmartlink_start_smartlink(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)36 static int _ksmartlink_start_smartlink(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
37 {
38 #ifdef KSMARTLINK_DEBUG
39     printk(KERN_INFO "%s\n", __FUNCTION__);
40 #endif
41     ssv_smartlink_status = 1;
42     *pOutBufLen = 0;
43     return 0;
44 }
ksmartlink_smartlink_started(void)45 int ksmartlink_smartlink_started(void)
46 {
47     return ssv_smartlink_status;
48 }
49 EXPORT_SYMBOL(ksmartlink_smartlink_started);
_ksmartlink_stop_smartlink(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)50 static int _ksmartlink_stop_smartlink(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
51 {
52 #ifdef KSMARTLINK_DEBUG
53     printk(KERN_INFO "%s\n", __FUNCTION__);
54 #endif
55     ssv_smartlink_status = 0;
56     *pOutBufLen = 0;
57     return 0;
58 }
_ksmartlink_set_channel(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)59 static int _ksmartlink_set_channel(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
60 {
61     int ret=-10;
62     int ch=(int)(*pInBuf);
63     struct ssv_softc *sc=ssv_smartlink_sc;
64 #ifdef KSMARTLINK_DEBUG
65     printk(KERN_INFO "%s %d\n", __FUNCTION__, ch);
66 #endif
67     if (!sc)
68     {
69         goto out;
70     }
71     mutex_lock(&sc->mutex);
72     ret = ssv6xxx_set_channel(sc, ch);
73     mutex_unlock(&sc->mutex);
74     *pOutBufLen = 0;
75 out:
76     return ret;
77 }
_ksmartlink_get_channel(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)78 static int _ksmartlink_get_channel(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
79 {
80     int ret=-10;
81     int ch=0;
82     struct ssv_softc *sc=ssv_smartlink_sc;
83 #ifdef KSMARTLINK_DEBUG
84     printk(KERN_INFO "%s\n", __FUNCTION__);
85 #endif
86     if (!sc)
87     {
88         goto out;
89     }
90     mutex_lock(&sc->mutex);
91     ret = ssv6xxx_get_channel(sc, &ch);
92     mutex_unlock(&sc->mutex);
93     *pOutBuf = ch;
94     *pOutBufLen = 1;
95 #ifdef KSMARTLINK_DEBUG
96     printk(KERN_INFO "%s %d\n", __FUNCTION__, ch);
97 #endif
98 out:
99     return ret;
100 }
_ksmartlink_set_promisc(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)101 static int _ksmartlink_set_promisc(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
102 {
103     int ret=-10;
104     int accept=(int)(*pInBuf);
105     struct ssv_softc *sc=ssv_smartlink_sc;
106 #ifdef KSMARTLINK_DEBUG
107     printk(KERN_INFO "%s %d\n", __FUNCTION__, accept);
108 #endif
109     if (!sc)
110     {
111         goto out;
112     }
113     mutex_lock(&sc->mutex);
114     ret = ssv6xxx_set_promisc(sc, accept);
115     mutex_unlock(&sc->mutex);
116     *pOutBufLen = 0;
117 out:
118     return ret;
119 }
_ksmartlink_get_promisc(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)120 static int _ksmartlink_get_promisc(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
121 {
122     int ret=-10;
123     int accept=(int)(*pInBuf);
124     struct ssv_softc *sc=ssv_smartlink_sc;
125 #ifdef KSMARTLINK_DEBUG
126     printk(KERN_INFO "%s\n", __FUNCTION__);
127 #endif
128     if (!sc)
129     {
130         goto out;
131     }
132     mutex_lock(&sc->mutex);
133     ret = ssv6xxx_get_promisc(sc, &accept);
134     mutex_unlock(&sc->mutex);
135     *pOutBuf = accept;
136     *pOutBufLen = 1;
137 #ifdef KSMARTLINK_DEBUG
138     printk(KERN_INFO "%s %d\n", __FUNCTION__, accept);
139 #endif
140 out:
141     return ret;
142 }
143 #define SMARTLINK_CMD_FIXED_LEN (10)
144 #define SMARTLINK_CMD_FIXED_TOT_LEN (SMARTLINK_CMD_FIXED_LEN+1)
145 #define SMARTLINK_RES_FIXED_LEN (SMARTLINK_CMD_FIXED_LEN)
146 #define SMARTLINK_RES_FIXED_TOT_LEN (SMARTLINK_RES_FIXED_LEN+2)
147 struct ksmartlink_cmd
148 {
149     char *cmd;
150     int (*process_func)(u8 *, u32, u8 *, u32 *);
151 };
152 static struct ksmartlink_cmd _ksmartlink_cmd_table[] =
153 {
154     {"startairki", _ksmartlink_start_smartlink},
155     {"stopairkis", _ksmartlink_stop_smartlink},
156     {"setchannel", _ksmartlink_set_channel},
157     {"getchannel", _ksmartlink_get_channel},
158     {"setpromisc", _ksmartlink_set_promisc},
159     {"getpromisc", _ksmartlink_get_promisc},
160 };
161 static u32 _ksmartlink_cmd_table_size=sizeof(_ksmartlink_cmd_table)/sizeof(struct ksmartlink_cmd);
162 #ifdef KSMARTLINK_DEBUG
_ksmartlink_hex_dump(u8 * pInBuf,u32 inBufLen)163 static void _ksmartlink_hex_dump(u8 *pInBuf, u32 inBufLen)
164 {
165     u32 i=0;
166     printk(KERN_INFO "\nKernel Hex Dump(len=%d):\n", inBufLen);
167     printk(KERN_INFO ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
168     for (i=0; i<inBufLen; i++)
169     {
170         if ((i) && ((i & 0xf) == 0))
171         {
172             printk("\n");
173         }
174         printk("%02x ", pInBuf[i]);
175     }
176     printk(KERN_INFO "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n");
177 }
178 #endif
_ksmartlink_process_msg(u8 * pInBuf,u32 inBufLen,u8 * pOutBuf,u32 * pOutBufLen)179 static int _ksmartlink_process_msg(u8 *pInBuf, u32 inBufLen, u8 *pOutBuf, u32 *pOutBufLen)
180 {
181     int ret=0;
182     u32 i=0;
183     struct ksmartlink_cmd *pCmd;
184     if (!pInBuf || !pOutBuf || !pOutBufLen)
185     {
186         printk(KERN_ERR "NULL pointer\n");
187         return -1;
188     }
189     for (i=0; i<_ksmartlink_cmd_table_size; i++)
190     {
191         if (!strncmp(_ksmartlink_cmd_table[i].cmd, pInBuf, SMARTLINK_CMD_FIXED_LEN))
192         {
193             break;
194         }
195     }
196     if (i < _ksmartlink_cmd_table_size)
197     {
198         pCmd = &_ksmartlink_cmd_table[i];
199         if (!pCmd->process_func)
200         {
201             printk(KERN_ERR "CMD %s has NULL process_func\n", pCmd->cmd);
202             return -3;
203         }
204         ret = pCmd->process_func(pInBuf+SMARTLINK_CMD_FIXED_LEN, inBufLen, pOutBuf, pOutBufLen);
205     #ifdef CONFIG_SSV_NETLINK_RESPONSE
206         if (ret < 0)
207         {
208             *pOutBufLen = SMARTLINK_RES_FIXED_TOT_LEN;
209         }
210         else
211         {
212             if (*pOutBufLen > 0)
213             {
214                 pOutBuf[SMARTLINK_RES_FIXED_LEN] = (u8)ret;
215                 pOutBuf[SMARTLINK_RES_FIXED_LEN+1]= *pOutBuf;
216             }
217             else
218             {
219                 pOutBuf[SMARTLINK_RES_FIXED_LEN] = (u8)ret;
220                 pOutBuf[SMARTLINK_RES_FIXED_LEN+1]= 0;
221             }
222             *pOutBufLen = SMARTLINK_RES_FIXED_TOT_LEN;
223         }
224         memcpy(pOutBuf, pCmd->cmd, SMARTLINK_RES_FIXED_LEN);
225     #else
226         (void)pOutBuf;
227         (void)pOutBufLen;
228     #endif
229         return 0;
230     }
231     else
232     {
233         printk(KERN_INFO "Unknow CMD or Packet?\n");
234     }
235     return 0;
236 }
237 static u8 gkBuf[MAX_PAYLOAD]={0};
238 static int ssv_usr_pid=0;
smartlink_nl_recv_msg(struct sk_buff * skb)239 void smartlink_nl_recv_msg(struct sk_buff *skb)
240 {
241     struct nlmsghdr *nlh;
242 #ifdef CONFIG_SSV_NETLINK_RESPONSE
243     struct sk_buff *skb_out;
244 #endif
245     int ret=0;
246     u8 *pInBuf=NULL;
247     u32 inBufLen=0;
248     u32 outBufLen=0;
249     nlh = (struct nlmsghdr *)skb->data;
250     ssv_usr_pid = nlh->nlmsg_pid;
251     pInBuf = (u8 *)nlmsg_data(nlh);
252     inBufLen = nlmsg_len(nlh);
253     #ifdef KSMARTLINK_DEBUG
254     _ksmartlink_hex_dump(pInBuf, inBufLen);
255     #endif
256     outBufLen = 0;
257     memset(gkBuf, 0, MAX_PAYLOAD);
258     ret = _ksmartlink_process_msg(pInBuf, inBufLen, gkBuf, &outBufLen);
259 #ifdef CONFIG_SSV_NETLINK_RESPONSE
260     if (outBufLen == 0)
261     {
262         memcpy(gkBuf, "Nothing", 8);
263         outBufLen = strlen(gkBuf);
264     }
265     skb_out = nlmsg_new(outBufLen, 0);
266     if (!skb_out)
267     {
268         printk(KERN_ERR "Failed to allocate new skb\n");
269         return;
270     }
271     nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, outBufLen, 0);
272     NETLINK_CB(skb_out).dst_group = 0;
273     memcpy(nlmsg_data(nlh), gkBuf, outBufLen);
274     ret = nlmsg_unicast(nl_sk, skb_out, ssv_usr_pid);
275     if (ret < 0)
276     {
277         printk(KERN_ERR "Error while sending bak to user\n");
278     }
279 #endif
280     return;
281 }
smartlink_nl_send_msg(struct sk_buff * skb)282 void smartlink_nl_send_msg(struct sk_buff *skb)
283 {
284     struct nlmsghdr *nlh;
285     struct sk_buff *skb_out;
286     int ret=0;
287     u8 *pOutBuf=skb->data;
288     u32 outBufLen=skb->len;
289     #ifdef KSMARTLINK_DEBUG
290     #endif
291     skb_out = nlmsg_new(outBufLen, 0);
292     if (!skb_out)
293     {
294         printk(KERN_ERR "Allocate new skb failed!\n");
295         return;
296     }
297     nlh = nlmsg_put(skb_out, 0, 0, NLMSG_DONE, outBufLen, 0);
298     NETLINK_CB(skb_out).dst_group = 0;
299     memcpy(nlmsg_data(nlh), pOutBuf, outBufLen);
300     ret = nlmsg_unicast(nl_sk, skb_out, ssv_usr_pid);
301     if (ret < 0)
302     {
303         printk(KERN_ERR "nlmsg_unicast failed!\n");
304     }
305     kfree_skb(skb);
306     return;
307 }
308 EXPORT_SYMBOL(smartlink_nl_send_msg);
ksmartlink_init(void)309 int ksmartlink_init(void)
310 {
311 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
312     nl_sk = netlink_kernel_create(&init_net,
313                                   NETLINK_SMARTLINK,
314                                   0,
315                                   smartlink_nl_recv_msg,
316                                   NULL,
317                                   THIS_MODULE);
318 #else
319     struct netlink_kernel_cfg cfg =
320             {
321                 .groups = 0,
322                 .input = smartlink_nl_recv_msg,
323             };
324     nl_sk = netlink_kernel_create(&init_net,
325                                   NETLINK_SMARTLINK,
326                                   &cfg);
327 #endif
328     printk(KERN_INFO "***************SmartLink Init-S**************\n");
329     if(!nl_sk)
330     {
331         printk(KERN_ERR "Error creating socket.\n");
332         return -10;
333     }
334     printk(KERN_INFO "***************SmartLink Init-E**************\n");
335     return 0;
336 }
ksmartlink_exit(void)337 void ksmartlink_exit(void)
338 {
339     printk(KERN_INFO "%s\n", __FUNCTION__);
340     if (nl_sk)
341     {
342         netlink_kernel_release(nl_sk);
343         nl_sk = NULL;
344     }
345 }
346 #if (defined(CONFIG_SSV_SUPPORT_ANDROID)||defined(CONFIG_SSV_BUILD_AS_ONE_KO))
347 EXPORT_SYMBOL(ksmartlink_init);
348 EXPORT_SYMBOL(ksmartlink_exit);
349 #else
350 module_init(ksmartlink_init);
351 module_exit(ksmartlink_exit);
352 #endif
353