1/*
2 * WlanDrvWext.c
3 *
4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 *  * Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *  * Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in
15 *    the documentation and/or other materials provided with the
16 *    distribution.
17 *  * Neither the name Texas Instruments nor the names of its
18 *    contributors may be used to endorse or promote products derived
19 *    from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34
35/*
36 * src/wext.c
37 *
38 * Support for Linux Wireless Extensions
39 *
40 */
41#include <linux/types.h>
42#include <linux/socket.h>
43#include <linux/if.h>
44#include <linux/wireless.h>
45#include <net/iw_handler.h>
46#include "WlanDrvIf.h"
47#include "CmdHndlr.h"
48#include "CmdInterpretWext.h"
49#include "privateCmd.h"
50#include "DrvMain.h"
51
52/* Routine prototypes */
53
54int wlanDrvWext_Handler (struct net_device *dev,
55                         struct iw_request_info *info,
56                         void  *iw_req,
57                         void  *extra);
58
59static struct iw_statistics *wlanDrvWext_GetWirelessStats (struct net_device *dev);
60
61extern int wlanDrvIf_LoadFiles (TWlanDrvIfObj *drv, TLoaderFilesData *pInitInfo);
62extern int wlanDrvIf_Start (struct net_device *dev);
63extern int wlanDrvIf_Stop (struct net_device *dev);
64
65
66/* callbacks for WEXT commands */
67static const iw_handler aWextHandlers[] = {
68	(iw_handler) NULL,				            /* SIOCSIWCOMMIT */
69	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWNAME */
70	(iw_handler) NULL,				            /* SIOCSIWNWID */
71	(iw_handler) NULL,				            /* SIOCGIWNWID */
72	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWFREQ */
73	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWFREQ */
74	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWMODE */
75	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWMODE */
76	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWSENS */
77	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWSENS */
78	(iw_handler) NULL,                          /* SIOCSIWRANGE - not used */
79	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWRANGE */
80	(iw_handler) NULL,		                    /* SIOCSIWPRIV - not used */
81	(iw_handler) NULL,                    		/* SIOCGIWPRIV - kernel code */
82	(iw_handler) NULL,                          /* SIOCSIWSTATS - not used */
83	(iw_handler) wlanDrvWext_GetWirelessStats,  /* SIOCGIWSTATS - kernel code */
84	(iw_handler) NULL,		                    /* SIOCSIWSPY */
85	(iw_handler) NULL,		                    /* SIOCGIWSPY */
86	(iw_handler) NULL,		                    /* SIOCSIWTHRSPY */
87	(iw_handler) NULL,		                    /* SIOCGIWTHRSPY */
88	(iw_handler) wlanDrvWext_Handler,           /* SIOCSIWAP */
89	(iw_handler) wlanDrvWext_Handler,           /* SIOCGIWAP */
90	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWMLME */
91	(iw_handler) NULL,		        			/* SIOCGIWAPLIST */
92	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWSCAN */
93	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWSCAN */
94	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWESSID */
95	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWESSID */
96	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWNICKN */
97	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWNICKN */
98	(iw_handler) NULL,				            /* -- hole -- */
99	(iw_handler) NULL,				            /* -- hole -- */
100	(iw_handler) NULL,		        			/* SIOCSIWRATE */
101	(iw_handler) NULL,		        			/* SIOCGIWRATE */
102	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWRTS */
103	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWRTS */
104	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWFRAG */
105	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWFRAG */
106	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWTXPOW */
107	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWTXPOW */
108	(iw_handler) NULL,		        			/* SIOCSIWRETRY */
109	(iw_handler) NULL,		        			/* SIOCGIWRETRY */
110	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWENCODE */
111	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWENCODE */
112	(iw_handler) NULL,		        			/* SIOCSIWPOWER */
113	(iw_handler) NULL,		        			/* SIOCGIWPOWER */
114	(iw_handler) NULL,				            /* -- hole -- */
115	(iw_handler) NULL,				            /* -- hole -- */
116    (iw_handler) wlanDrvWext_Handler,           /* SIOCSIWGENIE */
117	(iw_handler) NULL,		        			/* SIOCGIWGENIE */
118	(iw_handler) wlanDrvWext_Handler,		    /* SIOCSIWAUTH */
119	(iw_handler) wlanDrvWext_Handler,		    /* SIOCGIWAUTH */
120	(iw_handler) wlanDrvWext_Handler,	        /* SIOCSIWENCODEEXT */
121	(iw_handler) NULL,	            			/* SIOCGIWENCODEEXT */
122	(iw_handler) wlanDrvWext_Handler, 			/* SIOCSIWPMKSA */
123};
124
125/* callbacks for private commands */
126static const iw_handler aPrivateHandlers[] = {
127	(iw_handler) wlanDrvWext_Handler,		    /* SIOCIWFIRSTPRIV+0 (set) */
128	(iw_handler) wlanDrvWext_Handler,		    /* SIOCIWFIRSTPRIV+1 (get) */
129};
130
131/* Describe the level of WEXT support to kernel */
132static struct iw_handler_def tWextIf = {
133#define	N(a)	(sizeof (a) / sizeof (a[0]))
134	.standard		    = (iw_handler *) aWextHandlers,
135	.num_standard		= N(aWextHandlers),
136	.private		    = (iw_handler *) aPrivateHandlers,
137	.num_private		= N(aPrivateHandlers),
138	.private_args		= NULL,
139	.num_private_args	= 0,
140	.get_wireless_stats	= wlanDrvWext_GetWirelessStats,
141#undef N
142};
143
144/* Initialite WEXT support - Register callbacks in kernel */
145void wlanDrvWext_Init (struct net_device *dev)
146{
147#ifdef HOST_PLATFORM_OMAP3430
148   	dev->get_wireless_stats = wlanDrvWext_GetWirelessStats;
149#endif
150	dev->wireless_handlers = &tWextIf;
151
152}
153
154/* Return driver statistics */
155static struct iw_statistics *wlanDrvWext_GetWirelessStats(struct net_device *dev)
156{
157	TWlanDrvIfObj *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev);
158
159    return (struct iw_statistics *) cmdHndlr_GetStat (drv->tCommon.hCmdHndlr);
160}
161
162/* Generic callback for WEXT commands */
163
164int wlanDrvWext_Handler (struct net_device *dev,
165                     struct iw_request_info *info,
166                     void *iw_req,
167                     void *extra)
168{
169    int              rc;
170    TWlanDrvIfObj   *drv = (TWlanDrvIfObj *)NETDEV_GET_PRIVATE(dev);
171    ti_private_cmd_t my_command;
172    struct iw_mlme   mlme;
173	struct iw_scan_req scanreq;
174    void             *copy_to_buf=NULL, *param3=NULL;
175
176    os_memoryZero(drv, &my_command, sizeof(ti_private_cmd_t));
177    os_memoryZero(drv, &mlme,       sizeof(struct iw_mlme));
178	os_memoryZero(drv, &scanreq, sizeof(struct iw_scan_req));
179
180    switch (info->cmd)
181    {
182        case SIOCIWFIRSTPRIV:
183        {
184            void *copy_from_buf;
185
186            if (os_memoryCopyFromUser(drv, &my_command, ((union iwreq_data *)iw_req)->data.pointer, sizeof(ti_private_cmd_t)))
187            {
188                os_printf ("wlanDrvWext_Handler() os_memoryCopyFromUser FAILED !!!\n");
189                return TI_NOK;
190            }
191            if (IS_PARAM_FOR_MODULE(my_command.cmd, DRIVER_MODULE_PARAM))
192            {
193                /* If it's a driver level command, handle it here and exit */
194                switch (my_command.cmd)
195                {
196                    case DRIVER_INIT_PARAM:
197                        return wlanDrvIf_LoadFiles(drv, my_command.in_buffer);
198
199                    case DRIVER_START_PARAM:
200                        return wlanDrvIf_Start(dev);
201
202                    case DRIVER_STOP_PARAM:
203                        return wlanDrvIf_Stop(dev);
204
205                    case DRIVER_STATUS_PARAM:
206                        *(TI_UINT32 *)my_command.out_buffer =
207                           (drv->tCommon.eDriverState == DRV_STATE_RUNNING) ? TI_TRUE : TI_FALSE;
208                        return TI_OK;
209                }
210            }
211            /* if we are still here handle a normal private command*/
212
213            if ((my_command.in_buffer) && (my_command.in_buffer_len))
214            {
215                copy_from_buf        = my_command.in_buffer;
216                my_command.in_buffer = os_memoryAlloc(drv, my_command.in_buffer_len);
217                if (os_memoryCopyFromUser(drv, my_command.in_buffer, copy_from_buf, my_command.in_buffer_len))
218                {
219                    os_printf("wlanDrvWext_Handler() os_memoryCopyFromUser 1 FAILED !!!\n");
220                    return TI_NOK;
221                }
222            }
223            if ((my_command.out_buffer) && (my_command.out_buffer_len))
224            {
225                copy_to_buf          = my_command.out_buffer;
226                my_command.out_buffer = os_memoryAlloc(drv, my_command.out_buffer_len);
227            }
228            param3 = &my_command;
229        }
230        break;
231
232        case SIOCSIWMLME:
233        {
234            os_memoryCopyFromUser(drv, &mlme, ((union iwreq_data *)iw_req)->data.pointer, sizeof(struct iw_mlme));
235            param3 = &mlme;
236        }
237        break;
238     case SIOCSIWSCAN:
239     {
240	if (((union iwreq_data *)iw_req)->data.pointer) {
241		os_memoryCopyFromUser(drv, &scanreq, ((union iwreq_data *)iw_req)->data.pointer, sizeof(struct iw_scan_req));
242		param3 = &scanreq;
243	}
244     }
245     break;
246
247     case SIOCSIWGENIE:
248     {
249         TI_UINT16 ie_length = ((union iwreq_data *)iw_req)->data.length;
250         TI_UINT8 *ie_content = ((union iwreq_data *)iw_req)->data.pointer;
251
252         if ((ie_length == 0) && (ie_content == NULL)) {
253                 /* Do nothing, deleting the IE */
254         } else if ((ie_content != NULL) && (ie_length <= RSN_MAX_GENERIC_IE_LENGTH) && (ie_length > 0)) {
255                 /* One IE cannot be larger than RSN_MAX_GENERIC_IE_LENGTH bytes */
256                 my_command.in_buffer = os_memoryAlloc(drv, ie_length);
257                 os_memoryCopyFromUser(drv, my_command.in_buffer, ie_content, ie_length );
258                 param3 = my_command.in_buffer;
259         } else {
260                 return TI_NOK;
261         }
262     }
263	 break;
264   }
265    /* If the friver is not running, return NOK */
266    if (drv->tCommon.eDriverState != DRV_STATE_RUNNING)
267    {
268        if (my_command.in_buffer)
269            os_memoryFree(drv, my_command.in_buffer, my_command.in_buffer_len);
270        if (my_command.out_buffer)
271            os_memoryFree(drv,my_command.out_buffer,my_command.out_buffer_len);
272        return TI_NOK;
273    }
274
275    /* Call the Cmd module with the given user paramters */
276    rc = cmdHndlr_InsertCommand(drv->tCommon.hCmdHndlr,
277                                   info->cmd,
278                                   info->flags,
279                                   iw_req,
280                                   0,
281                                   extra,
282                                   0,
283                                   param3,
284                                   NULL);
285    /* Here we are after the command was completed */
286    if (my_command.in_buffer)
287    {
288        os_memoryFree(drv, my_command.in_buffer, my_command.in_buffer_len);
289    }
290    if (my_command.out_buffer)
291    {
292        if (os_memoryCopyToUser(drv, copy_to_buf, my_command.out_buffer, my_command.out_buffer_len))
293        {
294            os_printf("wlanDrvWext_Handler() os_memoryCopyToUser FAILED !!!\n");
295            rc = TI_NOK;
296        }
297        os_memoryFree(drv, my_command.out_buffer, my_command.out_buffer_len);
298    }
299    return rc;
300}
301